aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2016-12-13 08:34:02 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-12-14 05:33:14 -0500
commit18e615ad87bce9125ef3990377a4a946ec0f21f3 (patch)
tree12b07989424ec6372daceec62adbef86576d0049
parentefcae7c931b473285e38c778bdaa9f36de9f78d6 (diff)
crypto: skcipher - fix crash in virtual walk
The new skcipher walk API may crash in the following way. (Interestingly, the tcrypt boot time tests seem unaffected, while an explicit test using the module triggers it) Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... [<ffff000008431d84>] __memcpy+0x84/0x180 [<ffff0000083ec0d0>] skcipher_walk_done+0x328/0x340 [<ffff0000080c5c04>] ctr_encrypt+0x84/0x100 [<ffff000008406d60>] simd_skcipher_encrypt+0x88/0x98 [<ffff0000083fa05c>] crypto_rfc3686_crypt+0x8c/0x98 [<ffff0000009b0900>] test_skcipher_speed+0x518/0x820 [tcrypt] [<ffff0000009b31c0>] do_test+0x1408/0x3b70 [tcrypt] [<ffff0000009bd050>] tcrypt_mod_init+0x50/0x1000 [tcrypt] [<ffff0000080838f4>] do_one_initcall+0x44/0x138 [<ffff0000081aee60>] do_init_module+0x68/0x1e0 [<ffff0000081524d0>] load_module+0x1fd0/0x2458 [<ffff000008152c38>] SyS_finit_module+0xe0/0xf0 [<ffff0000080836f0>] el0_svc_naked+0x24/0x28 This is due to the fact that skcipher_done_slow() may be entered with walk->buffer unset. Since skcipher_walk_done() already deals with the case where walk->buffer == walk->page, it appears to be the intention that walk->buffer point to walk->page after skcipher_next_slow(), so ensure that is the case. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/skcipher.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index aca07c643d41..0e1e6c35188e 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -226,7 +226,9 @@ static int skcipher_next_slow(struct skcipher_walk *walk, unsigned int bsize)
226 void *v; 226 void *v;
227 227
228 if (!phys) { 228 if (!phys) {
229 buffer = walk->buffer ?: walk->page; 229 if (!walk->buffer)
230 walk->buffer = walk->page;
231 buffer = walk->buffer;
230 if (buffer) 232 if (buffer)
231 goto ok; 233 goto ok;
232 } 234 }