crypto: xts - Handle EBUSY correctly
authorHerbert Xu <herbert@gondor.apana.org.au>
Sun, 22 Jan 2023 08:07:37 +0000 (16:07 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:32:57 +0000 (09:32 +0100)
[ Upstream commit 51c082514c2dedf2711c99d93c196cc4eedceb40 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
crypto/xts.c

index 63c85b9..de6cbcf 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;
                }
        }