Commit f8b0d4d0 authored by Herbert Xu's avatar Herbert Xu

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: default avatarShasi Pulijala <spulijala@amcc.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 29ecd4ab
...@@ -280,29 +280,13 @@ static struct notifier_block cryptomgr_notifier = { ...@@ -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); ...@@ -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)
......
...@@ -107,9 +107,6 @@ struct alg_test_desc { ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) ...@@ -2245,41 +2295,3 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
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]);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment