Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8b0d4d0 authored by Herbert Xu's avatar Herbert Xu
Browse files

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
Loading
Loading
Loading
Loading
+1 −17
Original line number Diff line number Diff line
@@ -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);
+0 −3
Original line number Diff line number Diff line
@@ -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)
+60 −48
Original line number Diff line number Diff line
@@ -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,
@@ -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)
{
@@ -137,8 +161,12 @@ 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);

@@ -146,7 +174,6 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
	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,
@@ -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;
}

@@ -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;
@@ -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";
@@ -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;
	}

@@ -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;
}

@@ -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";
@@ -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;
}

@@ -655,7 +700,6 @@ 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];
@@ -663,6 +707,11 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc,
	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";
@@ -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;
	}

@@ -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;
}

@@ -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]);
}