crypto: xts - Handle EBUSY correctly
authorHerbert Xu <herbert@gondor.apana.org.au>
Sun, 22 Jan 2023 08:07:37 +0000 (16:07 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 27 Jan 2023 10:58:09 +0000 (18:58 +0800)
As it is xts only handles the special return value of EINPROGRESS,
which means that in all other cases it will free data related to the
request.

However, as the caller of xts may specify MAY_BACKLOG, we also need
to expect EBUSY and treat it in the same way.  Otherwise backlogged
requests will trigger a use-after-free.

Fixes: 8083b1bf8163 ("crypto: xts - add support for ciphertext stealing")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/xts.c

index 63c85b9e64e08df7d1ff88c61560e3a70b2232a4..de6cbcf69bbd652090df85d19d029ec5b4b1082f 100644 (file)
@@ -203,12 +203,12 @@ static void xts_encrypt_done(struct crypto_async_request *areq, int err)
        if (!err) {
                struct xts_request_ctx *rctx = skcipher_request_ctx(req);
 
-               rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+               rctx->subreq.base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
                err = xts_xor_tweak_post(req, true);
 
                if (!err && unlikely(req->cryptlen % XTS_BLOCK_SIZE)) {
                        err = xts_cts_final(req, crypto_skcipher_encrypt);
-                       if (err == -EINPROGRESS)
+                       if (err == -EINPROGRESS || err == -EBUSY)
                                return;
                }
        }
@@ -223,12 +223,12 @@ static void xts_decrypt_done(struct crypto_async_request *areq, int err)
        if (!err) {
                struct xts_request_ctx *rctx = skcipher_request_ctx(req);
 
-               rctx->subreq.base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+               rctx->subreq.base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
                err = xts_xor_tweak_post(req, false);
 
                if (!err && unlikely(req->cryptlen % XTS_BLOCK_SIZE)) {
                        err = xts_cts_final(req, crypto_skcipher_decrypt);
-                       if (err == -EINPROGRESS)
+                       if (err == -EINPROGRESS || err == -EBUSY)
                                return;
                }
        }