diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-05-06 02:15:47 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2009-06-02 00:04:45 -0400 |
commit | f8b0d4d09dc9d0a73fcdcf6c2724650529ec417d (patch) | |
tree | 922fed01215af467ce07778268466b3c50b09120 /crypto | |
parent | 29ecd4ab3d3aa8bb231361937165dfbbbc534e9a (diff) |
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>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/algboss.c | 18 | ||||
-rw-r--r-- | crypto/internal.h | 3 | ||||
-rw-r--r-- | crypto/testmgr.c | 108 |
3 files changed, 61 insertions, 68 deletions
diff --git a/crypto/algboss.c b/crypto/algboss.c index 6906f92aeac0..9908dd830c26 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c | |||
@@ -280,29 +280,13 @@ static struct notifier_block cryptomgr_notifier = { | |||
280 | 280 | ||
281 | static int __init cryptomgr_init(void) | 281 | static int __init cryptomgr_init(void) |
282 | { | 282 | { |
283 | int err; | 283 | return crypto_register_notifier(&cryptomgr_notifier); |
284 | |||
285 | err = testmgr_init(); | ||
286 | if (err) | ||
287 | return err; | ||
288 | |||
289 | err = crypto_register_notifier(&cryptomgr_notifier); | ||
290 | if (err) | ||
291 | goto free_testmgr; | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | free_testmgr: | ||
296 | testmgr_exit(); | ||
297 | return err; | ||
298 | } | 284 | } |
299 | 285 | ||
300 | static void __exit cryptomgr_exit(void) | 286 | static void __exit cryptomgr_exit(void) |
301 | { | 287 | { |
302 | int err = crypto_unregister_notifier(&cryptomgr_notifier); | 288 | int err = crypto_unregister_notifier(&cryptomgr_notifier); |
303 | BUG_ON(err); | 289 | BUG_ON(err); |
304 | |||
305 | testmgr_exit(); | ||
306 | } | 290 | } |
307 | 291 | ||
308 | subsys_initcall(cryptomgr_init); | 292 | subsys_initcall(cryptomgr_init); |
diff --git a/crypto/internal.h b/crypto/internal.h index fc76e1f37fc3..113579a82dff 100644 --- a/crypto/internal.h +++ b/crypto/internal.h | |||
@@ -121,9 +121,6 @@ int crypto_register_notifier(struct notifier_block *nb); | |||
121 | int crypto_unregister_notifier(struct notifier_block *nb); | 121 | int crypto_unregister_notifier(struct notifier_block *nb); |
122 | int crypto_probing_notify(unsigned long val, void *v); | 122 | int crypto_probing_notify(unsigned long val, void *v); |
123 | 123 | ||
124 | int __init testmgr_init(void); | ||
125 | void testmgr_exit(void); | ||
126 | |||
127 | static inline void crypto_alg_put(struct crypto_alg *alg) | 124 | static inline void crypto_alg_put(struct crypto_alg *alg) |
128 | { | 125 | { |
129 | if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) | 126 | if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) |
diff --git a/crypto/testmgr.c b/crypto/testmgr.c index e76af78d2fa0..c5550943411d 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c | |||
@@ -107,9 +107,6 @@ struct alg_test_desc { | |||
107 | 107 | ||
108 | static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; | 108 | static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; |
109 | 109 | ||
110 | static char *xbuf[XBUFSIZE]; | ||
111 | static char *axbuf[XBUFSIZE]; | ||
112 | |||
113 | static void hexdump(unsigned char *buf, unsigned int len) | 110 | static void hexdump(unsigned char *buf, unsigned int len) |
114 | { | 111 | { |
115 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, | 112 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, |
@@ -128,6 +125,33 @@ static void tcrypt_complete(struct crypto_async_request *req, int err) | |||
128 | complete(&res->completion); | 125 | complete(&res->completion); |
129 | } | 126 | } |
130 | 127 | ||
128 | static int testmgr_alloc_buf(char *buf[XBUFSIZE]) | ||
129 | { | ||
130 | int i; | ||
131 | |||
132 | for (i = 0; i < XBUFSIZE; i++) { | ||
133 | buf[i] = (void *)__get_free_page(GFP_KERNEL); | ||
134 | if (!buf[i]) | ||
135 | goto err_free_buf; | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | |||
140 | err_free_buf: | ||
141 | while (i-- > 0) | ||
142 | free_page((unsigned long)buf[i]); | ||
143 | |||
144 | return -ENOMEM; | ||
145 | } | ||
146 | |||
147 | static void testmgr_free_buf(char *buf[XBUFSIZE]) | ||
148 | { | ||
149 | int i; | ||
150 | |||
151 | for (i = 0; i < XBUFSIZE; i++) | ||
152 | free_page((unsigned long)buf[i]); | ||
153 | } | ||
154 | |||
131 | static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | 155 | static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, |
132 | unsigned int tcount) | 156 | unsigned int tcount) |
133 | { | 157 | { |
@@ -137,8 +161,12 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | |||
137 | char result[64]; | 161 | char result[64]; |
138 | struct ahash_request *req; | 162 | struct ahash_request *req; |
139 | struct tcrypt_result tresult; | 163 | struct tcrypt_result tresult; |
140 | int ret; | ||
141 | void *hash_buff; | 164 | void *hash_buff; |
165 | char *xbuf[XBUFSIZE]; | ||
166 | int ret = -ENOMEM; | ||
167 | |||
168 | if (testmgr_alloc_buf(xbuf)) | ||
169 | goto out_nobuf; | ||
142 | 170 | ||
143 | init_completion(&tresult.completion); | 171 | init_completion(&tresult.completion); |
144 | 172 | ||
@@ -146,7 +174,6 @@ static int test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, | |||
146 | if (!req) { | 174 | if (!req) { |
147 | printk(KERN_ERR "alg: hash: Failed to allocate request for " | 175 | printk(KERN_ERR "alg: hash: Failed to allocate request for " |
148 | "%s\n", algo); | 176 | "%s\n", algo); |
149 | ret = -ENOMEM; | ||
150 | goto out_noreq; | 177 | goto out_noreq; |
151 | } | 178 | } |
152 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | 179 | 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 | out: | 299 | out: |
273 | ahash_request_free(req); | 300 | ahash_request_free(req); |
274 | out_noreq: | 301 | out_noreq: |
302 | testmgr_free_buf(xbuf); | ||
303 | out_nobuf: | ||
275 | return ret; | 304 | return ret; |
276 | } | 305 | } |
277 | 306 | ||
@@ -280,7 +309,7 @@ static int test_aead(struct crypto_aead *tfm, int enc, | |||
280 | { | 309 | { |
281 | const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); | 310 | const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); |
282 | unsigned int i, j, k, n, temp; | 311 | unsigned int i, j, k, n, temp; |
283 | int ret = 0; | 312 | int ret = -ENOMEM; |
284 | char *q; | 313 | char *q; |
285 | char *key; | 314 | char *key; |
286 | struct aead_request *req; | 315 | struct aead_request *req; |
@@ -292,6 +321,13 @@ static int test_aead(struct crypto_aead *tfm, int enc, | |||
292 | void *input; | 321 | void *input; |
293 | void *assoc; | 322 | void *assoc; |
294 | char iv[MAX_IVLEN]; | 323 | char iv[MAX_IVLEN]; |
324 | char *xbuf[XBUFSIZE]; | ||
325 | char *axbuf[XBUFSIZE]; | ||
326 | |||
327 | if (testmgr_alloc_buf(xbuf)) | ||
328 | goto out_noxbuf; | ||
329 | if (testmgr_alloc_buf(axbuf)) | ||
330 | goto out_noaxbuf; | ||
295 | 331 | ||
296 | if (enc == ENCRYPT) | 332 | if (enc == ENCRYPT) |
297 | e = "encryption"; | 333 | e = "encryption"; |
@@ -304,7 +340,6 @@ static int test_aead(struct crypto_aead *tfm, int enc, | |||
304 | if (!req) { | 340 | if (!req) { |
305 | printk(KERN_ERR "alg: aead: Failed to allocate request for " | 341 | printk(KERN_ERR "alg: aead: Failed to allocate request for " |
306 | "%s\n", algo); | 342 | "%s\n", algo); |
307 | ret = -ENOMEM; | ||
308 | goto out; | 343 | goto out; |
309 | } | 344 | } |
310 | 345 | ||
@@ -581,6 +616,10 @@ static int test_aead(struct crypto_aead *tfm, int enc, | |||
581 | 616 | ||
582 | out: | 617 | out: |
583 | aead_request_free(req); | 618 | aead_request_free(req); |
619 | testmgr_free_buf(axbuf); | ||
620 | out_noaxbuf: | ||
621 | testmgr_free_buf(xbuf); | ||
622 | out_noxbuf: | ||
584 | return ret; | 623 | return ret; |
585 | } | 624 | } |
586 | 625 | ||
@@ -589,10 +628,14 @@ static int test_cipher(struct crypto_cipher *tfm, int enc, | |||
589 | { | 628 | { |
590 | const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm)); | 629 | const char *algo = crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm)); |
591 | unsigned int i, j, k; | 630 | unsigned int i, j, k; |
592 | int ret; | ||
593 | char *q; | 631 | char *q; |
594 | const char *e; | 632 | const char *e; |
595 | void *data; | 633 | void *data; |
634 | char *xbuf[XBUFSIZE]; | ||
635 | int ret = -ENOMEM; | ||
636 | |||
637 | if (testmgr_alloc_buf(xbuf)) | ||
638 | goto out_nobuf; | ||
596 | 639 | ||
597 | if (enc == ENCRYPT) | 640 | if (enc == ENCRYPT) |
598 | e = "encryption"; | 641 | e = "encryption"; |
@@ -646,6 +689,8 @@ static int test_cipher(struct crypto_cipher *tfm, int enc, | |||
646 | ret = 0; | 689 | ret = 0; |
647 | 690 | ||
648 | out: | 691 | out: |
692 | testmgr_free_buf(xbuf); | ||
693 | out_nobuf: | ||
649 | return ret; | 694 | return ret; |
650 | } | 695 | } |
651 | 696 | ||
@@ -655,7 +700,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
655 | const char *algo = | 700 | const char *algo = |
656 | crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); | 701 | crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); |
657 | unsigned int i, j, k, n, temp; | 702 | unsigned int i, j, k, n, temp; |
658 | int ret; | ||
659 | char *q; | 703 | char *q; |
660 | struct ablkcipher_request *req; | 704 | struct ablkcipher_request *req; |
661 | struct scatterlist sg[8]; | 705 | struct scatterlist sg[8]; |
@@ -663,6 +707,11 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
663 | struct tcrypt_result result; | 707 | struct tcrypt_result result; |
664 | void *data; | 708 | void *data; |
665 | char iv[MAX_IVLEN]; | 709 | char iv[MAX_IVLEN]; |
710 | char *xbuf[XBUFSIZE]; | ||
711 | int ret = -ENOMEM; | ||
712 | |||
713 | if (testmgr_alloc_buf(xbuf)) | ||
714 | goto out_nobuf; | ||
666 | 715 | ||
667 | if (enc == ENCRYPT) | 716 | if (enc == ENCRYPT) |
668 | e = "encryption"; | 717 | e = "encryption"; |
@@ -675,7 +724,6 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
675 | if (!req) { | 724 | if (!req) { |
676 | printk(KERN_ERR "alg: skcipher: Failed to allocate request " | 725 | printk(KERN_ERR "alg: skcipher: Failed to allocate request " |
677 | "for %s\n", algo); | 726 | "for %s\n", algo); |
678 | ret = -ENOMEM; | ||
679 | goto out; | 727 | goto out; |
680 | } | 728 | } |
681 | 729 | ||
@@ -860,6 +908,8 @@ static int test_skcipher(struct crypto_ablkcipher *tfm, int enc, | |||
860 | 908 | ||
861 | out: | 909 | out: |
862 | ablkcipher_request_free(req); | 910 | ablkcipher_request_free(req); |
911 | testmgr_free_buf(xbuf); | ||
912 | out_nobuf: | ||
863 | return ret; | 913 | return ret; |
864 | } | 914 | } |
865 | 915 | ||
@@ -2245,41 +2295,3 @@ notest: | |||
2245 | return 0; | 2295 | return 0; |
2246 | } | 2296 | } |
2247 | EXPORT_SYMBOL_GPL(alg_test); | 2297 | EXPORT_SYMBOL_GPL(alg_test); |
2248 | |||
2249 | int __init testmgr_init(void) | ||
2250 | { | ||
2251 | int i; | ||
2252 | |||
2253 | for (i = 0; i < XBUFSIZE; i++) { | ||
2254 | xbuf[i] = (void *)__get_free_page(GFP_KERNEL); | ||
2255 | if (!xbuf[i]) | ||
2256 | goto err_free_xbuf; | ||
2257 | } | ||
2258 | |||
2259 | for (i = 0; i < XBUFSIZE; i++) { | ||
2260 | axbuf[i] = (void *)__get_free_page(GFP_KERNEL); | ||
2261 | if (!axbuf[i]) | ||
2262 | goto err_free_axbuf; | ||
2263 | } | ||
2264 | |||
2265 | return 0; | ||
2266 | |||
2267 | err_free_axbuf: | ||
2268 | for (i = 0; i < XBUFSIZE && axbuf[i]; i++) | ||
2269 | free_page((unsigned long)axbuf[i]); | ||
2270 | err_free_xbuf: | ||
2271 | for (i = 0; i < XBUFSIZE && xbuf[i]; i++) | ||
2272 | free_page((unsigned long)xbuf[i]); | ||
2273 | |||
2274 | return -ENOMEM; | ||
2275 | } | ||
2276 | |||
2277 | void testmgr_exit(void) | ||
2278 | { | ||
2279 | int i; | ||
2280 | |||
2281 | for (i = 0; i < XBUFSIZE; i++) | ||
2282 | free_page((unsigned long)axbuf[i]); | ||
2283 | for (i = 0; i < XBUFSIZE; i++) | ||
2284 | free_page((unsigned long)xbuf[i]); | ||
2285 | } | ||