Skip to content

Commit

Permalink
crypto: testmgr - Dynamically allocate xbuf and axbuf
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
herbertx committed Jun 2, 2009
1 parent 29ecd4a commit f8b0d4d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 68 deletions.
18 changes: 1 addition & 17 deletions crypto/algboss.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,29 +280,13 @@ static struct notifier_block cryptomgr_notifier = {

static int __init cryptomgr_init(void)
{
int err;

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;
return crypto_register_notifier(&cryptomgr_notifier);
}

static void __exit cryptomgr_exit(void)
{
int err = crypto_unregister_notifier(&cryptomgr_notifier);
BUG_ON(err);

testmgr_exit();
}

subsys_initcall(cryptomgr_init);
Expand Down
3 changes: 0 additions & 3 deletions crypto/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ int crypto_register_notifier(struct notifier_block *nb);
int crypto_unregister_notifier(struct notifier_block *nb);
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)
{
if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
Expand Down
108 changes: 60 additions & 48 deletions crypto/testmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,6 @@ struct alg_test_desc {

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)
{
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
Expand All @@ -128,6 +125,33 @@ static void tcrypt_complete(struct crypto_async_request *req, int err)
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,
unsigned int tcount)
{
Expand All @@ -137,16 +161,19 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
char result[64];
struct ahash_request *req;
struct tcrypt_result tresult;
int ret;
void *hash_buff;
char *xbuf[XBUFSIZE];
int ret = -ENOMEM;

if (testmgr_alloc_buf(xbuf))
goto out_nobuf;

init_completion(&tresult.completion);

req = ahash_request_alloc(tfm, GFP_KERNEL);
if (!req) {
printk(KERN_ERR "alg: hash: Failed to allocate request for "
"%s\n", algo);
ret = -ENOMEM;
goto out_noreq;
}
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
Expand Down Expand Up @@ -272,6 +299,8 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
out:
ahash_request_free(req);
out_noreq:
testmgr_free_buf(xbuf);
out_nobuf:
return ret;
}

Expand All @@ -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));
unsigned int i, j, k, n, temp;
int ret = 0;
int ret = -ENOMEM;
char *q;
char *key;
struct aead_request *req;
Expand All @@ -292,6 +321,13 @@ static int test_aead(struct crypto_aead *tfm, int enc,
void *input;
void *assoc;
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)
e = "encryption";
Expand All @@ -304,7 +340,6 @@ static int test_aead(struct crypto_aead *tfm, int enc,
if (!req) {
printk(KERN_ERR "alg: aead: Failed to allocate request for "
"%s\n", algo);
ret = -ENOMEM;
goto out;
}

Expand Down Expand Up @@ -581,6 +616,10 @@ static int test_aead(struct crypto_aead *tfm, int enc,

out:
aead_request_free(req);
testmgr_free_buf(axbuf);
out_noaxbuf:
testmgr_free_buf(xbuf);
out_noxbuf:
return ret;
}

Expand All @@ -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));
unsigned int i, j, k;
int ret;
char *q;
const char *e;
void *data;
char *xbuf[XBUFSIZE];
int ret = -ENOMEM;

if (testmgr_alloc_buf(xbuf))
goto out_nobuf;

if (enc == ENCRYPT)
e = "encryption";
Expand Down Expand Up @@ -646,6 +689,8 @@ static int test_cipher(struct crypto_cipher *tfm, int enc,
ret = 0;

out:
testmgr_free_buf(xbuf);
out_nobuf:
return ret;
}

Expand All @@ -655,14 +700,18 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
const char *algo =
crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
unsigned int i, j, k, n, temp;
int ret;
char *q;
struct ablkcipher_request *req;
struct scatterlist sg[8];
const char *e;
struct tcrypt_result result;
void *data;
char iv[MAX_IVLEN];
char *xbuf[XBUFSIZE];
int ret = -ENOMEM;

if (testmgr_alloc_buf(xbuf))
goto out_nobuf;

if (enc == ENCRYPT)
e = "encryption";
Expand All @@ -675,7 +724,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
if (!req) {
printk(KERN_ERR "alg: skcipher: Failed to allocate request "
"for %s\n", algo);
ret = -ENOMEM;
goto out;
}

Expand Down Expand Up @@ -860,6 +908,8 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,

out:
ablkcipher_request_free(req);
testmgr_free_buf(xbuf);
out_nobuf:
return ret;
}

Expand Down Expand Up @@ -2245,41 +2295,3 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
return 0;
}
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]);
}

0 comments on commit f8b0d4d

Please sign in to comment.