crypto: testmgr - Dynamically allocate xbuf and axbuf
We currently allocate temporary memory that is used for testing statically. This renders the testing engine non-reentrant. As algorithms may nest, i.e., one may construct another in order to carry out a part of its operation, this is unacceptable. For example, it has been reported that an AEAD implementation allocates a cipher in its setkey function, which causes it to fail during testing as the temporary memory is overwritten. This patch replaces the static memory with dynamically allocated buffers. We need a maximum of 16 pages so this slightly increases the chances of an algorithm failing due to memory shortage. However, as testing usually occurs at registration, this shouldn't be a big problem. Reported-by: Shasi Pulijala <spulijala@amcc.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
29ecd4ab3d
commit
f8b0d4d09d
|
@ -280,29 +280,13 @@ static struct notifier_block cryptomgr_notifier = {
|
||||||
|
|
||||||
static int __init cryptomgr_init(void)
|
static int __init cryptomgr_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
return crypto_register_notifier(&cryptomgr_notifier);
|
||||||
|
|
||||||
err = testmgr_init();
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = crypto_register_notifier(&cryptomgr_notifier);
|
|
||||||
if (err)
|
|
||||||
goto free_testmgr;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free_testmgr:
|
|
||||||
testmgr_exit();
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit cryptomgr_exit(void)
|
static void __exit cryptomgr_exit(void)
|
||||||
{
|
{
|
||||||
int err = crypto_unregister_notifier(&cryptomgr_notifier);
|
int err = crypto_unregister_notifier(&cryptomgr_notifier);
|
||||||
BUG_ON(err);
|
BUG_ON(err);
|
||||||
|
|
||||||
testmgr_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subsys_initcall(cryptomgr_init);
|
subsys_initcall(cryptomgr_init);
|
||||||
|
|
|
@ -121,9 +121,6 @@ int crypto_register_notifier(struct notifier_block *nb);
|
||||||
int crypto_unregister_notifier(struct notifier_block *nb);
|
int crypto_unregister_notifier(struct notifier_block *nb);
|
||||||
int crypto_probing_notify(unsigned long val, void *v);
|
int crypto_probing_notify(unsigned long val, void *v);
|
||||||
|
|
||||||
int __init testmgr_init(void);
|
|
||||||
void testmgr_exit(void);
|
|
||||||
|
|
||||||
static inline void crypto_alg_put(struct crypto_alg *alg)
|
static inline void crypto_alg_put(struct crypto_alg *alg)
|
||||||
{
|
{
|
||||||
if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
|
if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
|
||||||
|
|
108
crypto/testmgr.c
108
crypto/testmgr.c
|
@ -107,9 +107,6 @@ struct alg_test_desc {
|
||||||
|
|
||||||
static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
|
static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
|
||||||
|
|
||||||
static char *xbuf[XBUFSIZE];
|
|
||||||
static char *axbuf[XBUFSIZE];
|
|
||||||
|
|
||||||
static void hexdump(unsigned char *buf, unsigned int len)
|
static void hexdump(unsigned char *buf, unsigned int len)
|
||||||
{
|
{
|
||||||
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
|
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
|
||||||
|
@ -128,6 +125,33 @@ static void tcrypt_complete(struct crypto_async_request *req, int err)
|
||||||
complete(&res->completion);
|
complete(&res->completion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int testmgr_alloc_buf(char *buf[XBUFSIZE])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < XBUFSIZE; i++) {
|
||||||
|
buf[i] = (void *)__get_free_page(GFP_KERNEL);
|
||||||
|
if (!buf[i])
|
||||||
|
goto err_free_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_free_buf:
|
||||||
|
while (i-- > 0)
|
||||||
|
free_page((unsigned long)buf[i]);
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testmgr_free_buf(char *buf[XBUFSIZE])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < XBUFSIZE; i++)
|
||||||
|
free_page((unsigned long)buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
|
static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
|
||||||
unsigned int tcount)
|
unsigned int tcount)
|
||||||
{
|
{
|
||||||
|
@ -137,8 +161,12 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
|
||||||
char result[64];
|
char result[64];
|
||||||
struct ahash_request *req;
|
struct ahash_request *req;
|
||||||
struct tcrypt_result tresult;
|
struct tcrypt_result tresult;
|
||||||
int ret;
|
|
||||||
void *hash_buff;
|
void *hash_buff;
|
||||||
|
char *xbuf[XBUFSIZE];
|
||||||
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (testmgr_alloc_buf(xbuf))
|
||||||
|
goto out_nobuf;
|
||||||
|
|
||||||
init_completion(&tresult.completion);
|
init_completion(&tresult.completion);
|
||||||
|
|
||||||
|
@ -146,7 +174,6 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
|
||||||
if (!req) {
|
if (!req) {
|
||||||
printk(KERN_ERR "alg: hash: Failed to allocate request for "
|
printk(KERN_ERR "alg: hash: Failed to allocate request for "
|
||||||
"%s\n", algo);
|
"%s\n", algo);
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out_noreq;
|
goto out_noreq;
|
||||||
}
|
}
|
||||||
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||||
|
@ -272,6 +299,8 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
|
||||||
out:
|
out:
|
||||||
ahash_request_free(req);
|
ahash_request_free(req);
|
||||||
out_noreq:
|
out_noreq:
|
||||||
|
testmgr_free_buf(xbuf);
|
||||||
|
out_nobuf:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +309,7 @@ static int test_aead(struct crypto_aead *tfm, int enc,
|
||||||
{
|
{
|
||||||
const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
|
const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm));
|
||||||
unsigned int i, j, k, n, temp;
|
unsigned int i, j, k, n, temp;
|
||||||
int ret = 0;
|
int ret = -ENOMEM;
|
||||||
char *q;
|
char *q;
|
||||||
char *key;
|
char *key;
|
||||||
struct aead_request *req;
|
struct aead_request *req;
|
||||||
|
@ -292,6 +321,13 @@ static int test_aead(struct crypto_aead *tfm, int enc,
|
||||||
void *input;
|
void *input;
|
||||||
void *assoc;
|
void *assoc;
|
||||||
char iv[MAX_IVLEN];
|
char iv[MAX_IVLEN];
|
||||||
|
char *xbuf[XBUFSIZE];
|
||||||
|
char *axbuf[XBUFSIZE];
|
||||||
|
|
||||||
|
if (testmgr_alloc_buf(xbuf))
|
||||||
|
goto out_noxbuf;
|
||||||
|
if (testmgr_alloc_buf(axbuf))
|
||||||
|
goto out_noaxbuf;
|
||||||
|
|
||||||
if (enc == ENCRYPT)
|
if (enc == ENCRYPT)
|
||||||
e = "encryption";
|
e = "encryption";
|
||||||
|
@ -304,7 +340,6 @@ static int test_aead(struct crypto_aead *tfm, int enc,
|
||||||
if (!req) {
|
if (!req) {
|
||||||
printk(KERN_ERR "alg: aead: Failed to allocate request for "
|
printk(KERN_ERR "alg: aead: Failed to allocate request for "
|
||||||
"%s\n", algo);
|
"%s\n", algo);
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,6 +616,10 @@ static int test_aead(struct crypto_aead *tfm, int enc,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
aead_request_free(req);
|
aead_request_free(req);
|
||||||
|
testmgr_free_buf(axbuf);
|
||||||
|
out_noaxbuf:
|
||||||
|
testmgr_free_buf(xbuf);
|
||||||
|
out_noxbuf:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,10 +628,14 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
|
||||||
{
|
{
|
||||||
const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
|
const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm));
|
||||||
unsigned int i, j, k;
|
unsigned int i, j, k;
|
||||||
int ret;
|
|
||||||
char *q;
|
char *q;
|
||||||
const char *e;
|
const char *e;
|
||||||
void *data;
|
void *data;
|
||||||
|
char *xbuf[XBUFSIZE];
|
||||||
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (testmgr_alloc_buf(xbuf))
|
||||||
|
goto out_nobuf;
|
||||||
|
|
||||||
if (enc == ENCRYPT)
|
if (enc == ENCRYPT)
|
||||||
e = "encryption";
|
e = "encryption";
|
||||||
|
@ -646,6 +689,8 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
testmgr_free_buf(xbuf);
|
||||||
|
out_nobuf:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +700,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
|
||||||
const char *algo =
|
const char *algo =
|
||||||
crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
|
crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
|
||||||
unsigned int i, j, k, n, temp;
|
unsigned int i, j, k, n, temp;
|
||||||
int ret;
|
|
||||||
char *q;
|
char *q;
|
||||||
struct ablkcipher_request *req;
|
struct ablkcipher_request *req;
|
||||||
struct scatterlist sg[8];
|
struct scatterlist sg[8];
|
||||||
|
@ -663,6 +707,11 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
|
||||||
struct tcrypt_result result;
|
struct tcrypt_result result;
|
||||||
void *data;
|
void *data;
|
||||||
char iv[MAX_IVLEN];
|
char iv[MAX_IVLEN];
|
||||||
|
char *xbuf[XBUFSIZE];
|
||||||
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (testmgr_alloc_buf(xbuf))
|
||||||
|
goto out_nobuf;
|
||||||
|
|
||||||
if (enc == ENCRYPT)
|
if (enc == ENCRYPT)
|
||||||
e = "encryption";
|
e = "encryption";
|
||||||
|
@ -675,7 +724,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
|
||||||
if (!req) {
|
if (!req) {
|
||||||
printk(KERN_ERR "alg: skcipher: Failed to allocate request "
|
printk(KERN_ERR "alg: skcipher: Failed to allocate request "
|
||||||
"for %s\n", algo);
|
"for %s\n", algo);
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,6 +908,8 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ablkcipher_request_free(req);
|
ablkcipher_request_free(req);
|
||||||
|
testmgr_free_buf(xbuf);
|
||||||
|
out_nobuf:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2245,41 +2295,3 @@ notest:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(alg_test);
|
EXPORT_SYMBOL_GPL(alg_test);
|
||||||
|
|
||||||
int __init testmgr_init(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < XBUFSIZE; i++) {
|
|
||||||
xbuf[i] = (void *)__get_free_page(GFP_KERNEL);
|
|
||||||
if (!xbuf[i])
|
|
||||||
goto err_free_xbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < XBUFSIZE; i++) {
|
|
||||||
axbuf[i] = (void *)__get_free_page(GFP_KERNEL);
|
|
||||||
if (!axbuf[i])
|
|
||||||
goto err_free_axbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_free_axbuf:
|
|
||||||
for (i = 0; i < XBUFSIZE && axbuf[i]; i++)
|
|
||||||
free_page((unsigned long)axbuf[i]);
|
|
||||||
err_free_xbuf:
|
|
||||||
for (i = 0; i < XBUFSIZE && xbuf[i]; i++)
|
|
||||||
free_page((unsigned long)xbuf[i]);
|
|
||||||
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
void testmgr_exit(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < XBUFSIZE; i++)
|
|
||||||
free_page((unsigned long)axbuf[i]);
|
|
||||||
for (i = 0; i < XBUFSIZE; i++)
|
|
||||||
free_page((unsigned long)xbuf[i]);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue