summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-05-31 14:12:30 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-06-06 02:44:16 -0400
commit7545b6c2087f4ef0287c8c9b7eba6a728c67ff8e (patch)
treefa6af8dcbe0e98567bf9867f0e036762bb170fde
parent4bb02dbd31d7430200db0e8dfb96f9d716351627 (diff)
crypto: chacha20poly1305 - fix atomic sleep when using async algorithm
Clear the CRYPTO_TFM_REQ_MAY_SLEEP flag when the chacha20poly1305 operation is being continued from an async completion callback, since sleeping may not be allowed in that context. This is basically the same bug that was recently fixed in the xts and lrw templates. But, it's always been broken in chacha20poly1305 too. This was found using syzkaller in combination with the updated crypto self-tests which actually test the MAY_SLEEP flag now. Reproducer: python -c 'import socket; socket.socket(socket.AF_ALG, 5, 0).bind( ("aead", "rfc7539(cryptd(chacha20-generic),poly1305-generic)"))' Kernel output: BUG: sleeping function called from invalid context at include/crypto/algapi.h:426 in_atomic(): 1, irqs_disabled(): 0, pid: 1001, name: kworker/2:2 [...] CPU: 2 PID: 1001 Comm: kworker/2:2 Not tainted 5.2.0-rc2 #5 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-20181126_142135-anatol 04/01/2014 Workqueue: crypto cryptd_queue_worker Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x4d/0x6a lib/dump_stack.c:113 ___might_sleep kernel/sched/core.c:6138 [inline] ___might_sleep.cold.19+0x8e/0x9f kernel/sched/core.c:6095 crypto_yield include/crypto/algapi.h:426 [inline] crypto_hash_walk_done+0xd6/0x100 crypto/ahash.c:113 shash_ahash_update+0x41/0x60 crypto/shash.c:251 shash_async_update+0xd/0x10 crypto/shash.c:260 crypto_ahash_update include/crypto/hash.h:539 [inline] poly_setkey+0xf6/0x130 crypto/chacha20poly1305.c:337 poly_init+0x51/0x60 crypto/chacha20poly1305.c:364 async_done_continue crypto/chacha20poly1305.c:78 [inline] poly_genkey_done+0x15/0x30 crypto/chacha20poly1305.c:369 cryptd_skcipher_complete+0x29/0x70 crypto/cryptd.c:279 cryptd_skcipher_decrypt+0xcd/0x110 crypto/cryptd.c:339 cryptd_queue_worker+0x70/0xa0 crypto/cryptd.c:184 process_one_work+0x1ed/0x420 kernel/workqueue.c:2269 worker_thread+0x3e/0x3a0 kernel/workqueue.c:2415 kthread+0x11f/0x140 kernel/kthread.c:255 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352 Fixes: 71ebc4d1b27d ("crypto: chacha20poly1305 - Add a ChaCha20-Poly1305 AEAD construction, RFC7539") Cc: <stable@vger.kernel.org> # v4.2+ Cc: Martin Willi <martin@strongswan.org> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/chacha20poly1305.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c
index e38a2d61819a..acbbf010222e 100644
--- a/crypto/chacha20poly1305.c
+++ b/crypto/chacha20poly1305.c
@@ -65,6 +65,8 @@ struct chachapoly_req_ctx {
65 unsigned int cryptlen; 65 unsigned int cryptlen;
66 /* Actual AD, excluding IV */ 66 /* Actual AD, excluding IV */
67 unsigned int assoclen; 67 unsigned int assoclen;
68 /* request flags, with MAY_SLEEP cleared if needed */
69 u32 flags;
68 union { 70 union {
69 struct poly_req poly; 71 struct poly_req poly;
70 struct chacha_req chacha; 72 struct chacha_req chacha;
@@ -74,8 +76,12 @@ struct chachapoly_req_ctx {
74static inline void async_done_continue(struct aead_request *req, int err, 76static inline void async_done_continue(struct aead_request *req, int err,
75 int (*cont)(struct aead_request *)) 77 int (*cont)(struct aead_request *))
76{ 78{
77 if (!err) 79 if (!err) {
80 struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
81
82 rctx->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
78 err = cont(req); 83 err = cont(req);
84 }
79 85
80 if (err != -EINPROGRESS && err != -EBUSY) 86 if (err != -EINPROGRESS && err != -EBUSY)
81 aead_request_complete(req, err); 87 aead_request_complete(req, err);
@@ -142,7 +148,7 @@ static int chacha_decrypt(struct aead_request *req)
142 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 148 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
143 } 149 }
144 150
145 skcipher_request_set_callback(&creq->req, aead_request_flags(req), 151 skcipher_request_set_callback(&creq->req, rctx->flags,
146 chacha_decrypt_done, req); 152 chacha_decrypt_done, req);
147 skcipher_request_set_tfm(&creq->req, ctx->chacha); 153 skcipher_request_set_tfm(&creq->req, ctx->chacha);
148 skcipher_request_set_crypt(&creq->req, src, dst, 154 skcipher_request_set_crypt(&creq->req, src, dst,
@@ -186,7 +192,7 @@ static int poly_tail(struct aead_request *req)
186 memcpy(&preq->tail.cryptlen, &len, sizeof(len)); 192 memcpy(&preq->tail.cryptlen, &len, sizeof(len));
187 sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail)); 193 sg_set_buf(preq->src, &preq->tail, sizeof(preq->tail));
188 194
189 ahash_request_set_callback(&preq->req, aead_request_flags(req), 195 ahash_request_set_callback(&preq->req, rctx->flags,
190 poly_tail_done, req); 196 poly_tail_done, req);
191 ahash_request_set_tfm(&preq->req, ctx->poly); 197 ahash_request_set_tfm(&preq->req, ctx->poly);
192 ahash_request_set_crypt(&preq->req, preq->src, 198 ahash_request_set_crypt(&preq->req, preq->src,
@@ -217,7 +223,7 @@ static int poly_cipherpad(struct aead_request *req)
217 sg_init_table(preq->src, 1); 223 sg_init_table(preq->src, 1);
218 sg_set_buf(preq->src, &preq->pad, padlen); 224 sg_set_buf(preq->src, &preq->pad, padlen);
219 225
220 ahash_request_set_callback(&preq->req, aead_request_flags(req), 226 ahash_request_set_callback(&preq->req, rctx->flags,
221 poly_cipherpad_done, req); 227 poly_cipherpad_done, req);
222 ahash_request_set_tfm(&preq->req, ctx->poly); 228 ahash_request_set_tfm(&preq->req, ctx->poly);
223 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 229 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
@@ -248,7 +254,7 @@ static int poly_cipher(struct aead_request *req)
248 sg_init_table(rctx->src, 2); 254 sg_init_table(rctx->src, 2);
249 crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen); 255 crypt = scatterwalk_ffwd(rctx->src, crypt, req->assoclen);
250 256
251 ahash_request_set_callback(&preq->req, aead_request_flags(req), 257 ahash_request_set_callback(&preq->req, rctx->flags,
252 poly_cipher_done, req); 258 poly_cipher_done, req);
253 ahash_request_set_tfm(&preq->req, ctx->poly); 259 ahash_request_set_tfm(&preq->req, ctx->poly);
254 ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen); 260 ahash_request_set_crypt(&preq->req, crypt, NULL, rctx->cryptlen);
@@ -278,7 +284,7 @@ static int poly_adpad(struct aead_request *req)
278 sg_init_table(preq->src, 1); 284 sg_init_table(preq->src, 1);
279 sg_set_buf(preq->src, preq->pad, padlen); 285 sg_set_buf(preq->src, preq->pad, padlen);
280 286
281 ahash_request_set_callback(&preq->req, aead_request_flags(req), 287 ahash_request_set_callback(&preq->req, rctx->flags,
282 poly_adpad_done, req); 288 poly_adpad_done, req);
283 ahash_request_set_tfm(&preq->req, ctx->poly); 289 ahash_request_set_tfm(&preq->req, ctx->poly);
284 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen); 290 ahash_request_set_crypt(&preq->req, preq->src, NULL, padlen);
@@ -302,7 +308,7 @@ static int poly_ad(struct aead_request *req)
302 struct poly_req *preq = &rctx->u.poly; 308 struct poly_req *preq = &rctx->u.poly;
303 int err; 309 int err;
304 310
305 ahash_request_set_callback(&preq->req, aead_request_flags(req), 311 ahash_request_set_callback(&preq->req, rctx->flags,
306 poly_ad_done, req); 312 poly_ad_done, req);
307 ahash_request_set_tfm(&preq->req, ctx->poly); 313 ahash_request_set_tfm(&preq->req, ctx->poly);
308 ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen); 314 ahash_request_set_crypt(&preq->req, req->src, NULL, rctx->assoclen);
@@ -329,7 +335,7 @@ static int poly_setkey(struct aead_request *req)
329 sg_init_table(preq->src, 1); 335 sg_init_table(preq->src, 1);
330 sg_set_buf(preq->src, rctx->key, sizeof(rctx->key)); 336 sg_set_buf(preq->src, rctx->key, sizeof(rctx->key));
331 337
332 ahash_request_set_callback(&preq->req, aead_request_flags(req), 338 ahash_request_set_callback(&preq->req, rctx->flags,
333 poly_setkey_done, req); 339 poly_setkey_done, req);
334 ahash_request_set_tfm(&preq->req, ctx->poly); 340 ahash_request_set_tfm(&preq->req, ctx->poly);
335 ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key)); 341 ahash_request_set_crypt(&preq->req, preq->src, NULL, sizeof(rctx->key));
@@ -353,7 +359,7 @@ static int poly_init(struct aead_request *req)
353 struct poly_req *preq = &rctx->u.poly; 359 struct poly_req *preq = &rctx->u.poly;
354 int err; 360 int err;
355 361
356 ahash_request_set_callback(&preq->req, aead_request_flags(req), 362 ahash_request_set_callback(&preq->req, rctx->flags,
357 poly_init_done, req); 363 poly_init_done, req);
358 ahash_request_set_tfm(&preq->req, ctx->poly); 364 ahash_request_set_tfm(&preq->req, ctx->poly);
359 365
@@ -391,7 +397,7 @@ static int poly_genkey(struct aead_request *req)
391 397
392 chacha_iv(creq->iv, req, 0); 398 chacha_iv(creq->iv, req, 0);
393 399
394 skcipher_request_set_callback(&creq->req, aead_request_flags(req), 400 skcipher_request_set_callback(&creq->req, rctx->flags,
395 poly_genkey_done, req); 401 poly_genkey_done, req);
396 skcipher_request_set_tfm(&creq->req, ctx->chacha); 402 skcipher_request_set_tfm(&creq->req, ctx->chacha);
397 skcipher_request_set_crypt(&creq->req, creq->src, creq->src, 403 skcipher_request_set_crypt(&creq->req, creq->src, creq->src,
@@ -431,7 +437,7 @@ static int chacha_encrypt(struct aead_request *req)
431 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen); 437 dst = scatterwalk_ffwd(rctx->dst, req->dst, req->assoclen);
432 } 438 }
433 439
434 skcipher_request_set_callback(&creq->req, aead_request_flags(req), 440 skcipher_request_set_callback(&creq->req, rctx->flags,
435 chacha_encrypt_done, req); 441 chacha_encrypt_done, req);
436 skcipher_request_set_tfm(&creq->req, ctx->chacha); 442 skcipher_request_set_tfm(&creq->req, ctx->chacha);
437 skcipher_request_set_crypt(&creq->req, src, dst, 443 skcipher_request_set_crypt(&creq->req, src, dst,
@@ -449,6 +455,7 @@ static int chachapoly_encrypt(struct aead_request *req)
449 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 455 struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
450 456
451 rctx->cryptlen = req->cryptlen; 457 rctx->cryptlen = req->cryptlen;
458 rctx->flags = aead_request_flags(req);
452 459
453 /* encrypt call chain: 460 /* encrypt call chain:
454 * - chacha_encrypt/done() 461 * - chacha_encrypt/done()
@@ -470,6 +477,7 @@ static int chachapoly_decrypt(struct aead_request *req)
470 struct chachapoly_req_ctx *rctx = aead_request_ctx(req); 477 struct chachapoly_req_ctx *rctx = aead_request_ctx(req);
471 478
472 rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE; 479 rctx->cryptlen = req->cryptlen - POLY1305_DIGEST_SIZE;
480 rctx->flags = aead_request_flags(req);
473 481
474 /* decrypt call chain: 482 /* decrypt call chain:
475 * - poly_genkey/done() 483 * - poly_genkey/done()