From: Herbert Xu <herbert@gondor.apana.org.au>
To: Mikulas Patocka <mpatocka@redhat.com>
Cc: "David S. Miller" <davem@davemloft.net>,
Harald Freudenberger <freude@linux.ibm.com>,
Ingo Franzki <ifranzki@linux.ibm.com>,
linux-crypto@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>,
dengler@linux.ibm.com, linux-s390@vger.kernel.org,
dm-devel@lists.linux.dev, agk@redhat.com, snitzer@kernel.org,
Milan Broz <gmazyland@gmail.com>
Subject: [PATCH] crypto: authenc - Correctly pass EINPROGRESS back up to the caller
Date: Wed, 24 Sep 2025 18:20:17 +0800 [thread overview]
Message-ID: <aNPF4bjo6FbvujIx@gondor.apana.org.au> (raw)
In-Reply-To: <aNK6IMzUgslPVi3x@gondor.apana.org.au>
When authenc is invoked with MAY_BACKLOG, it needs to pass EINPROGRESS
notifications back up to the caller when the underlying algorithm
returns EBUSY synchronously.
However, if the EBUSY comes from the second part of an authenc call,
i.e., it is asynchronous, both the EBUSY and the subsequent EINPROGRESS
notification must not be passed to the caller.
Implement this by passing a mask to the function that starts the
second half of authenc and using it to determine whether EBUSY
and EINPROGRESS should be passed to the caller.
This was a deficiency in the original implementation of authenc
because it was not expected to be used with MAY_BACKLOG.
Reported-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reported-by: Mikulas Patocka <mpatocka@redhat.com>
Fixes: 180ce7e81030 ("crypto: authenc - Add EINPROGRESS check")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/crypto/authenc.c b/crypto/authenc.c
index a723769c8777..ac679ce2cb95 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -37,7 +37,7 @@ struct authenc_request_ctx {
static void authenc_request_complete(struct aead_request *req, int err)
{
- if (err != -EINPROGRESS)
+ if (err != -EINPROGRESS && err != -EBUSY)
aead_request_complete(req, err);
}
@@ -107,27 +107,42 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
return err;
}
-static void authenc_geniv_ahash_done(void *data, int err)
+static void authenc_geniv_ahash_finish(struct aead_request *req)
{
- struct aead_request *req = data;
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct aead_instance *inst = aead_alg_instance(authenc);
struct authenc_instance_ctx *ictx = aead_instance_ctx(inst);
struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
- if (err)
- goto out;
-
scatterwalk_map_and_copy(ahreq->result, req->dst,
req->assoclen + req->cryptlen,
crypto_aead_authsize(authenc), 1);
+}
-out:
+static void authenc_geniv_ahash_done(void *data, int err)
+{
+ struct aead_request *req = data;
+
+ if (!err)
+ authenc_geniv_ahash_finish(req);
aead_request_complete(req, err);
}
-static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
+/*
+ * Used when the ahash request was invoked in the async callback context
+ * of the previous skcipher request. Eat any EINPROGRESS notifications.
+ */
+static void authenc_geniv_ahash_done2(void *data, int err)
+{
+ struct aead_request *req = data;
+
+ if (!err)
+ authenc_geniv_ahash_finish(req);
+ authenc_request_complete(req, err);
+}
+
+static int crypto_authenc_genicv(struct aead_request *req, unsigned int mask)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct aead_instance *inst = aead_alg_instance(authenc);
@@ -136,6 +151,7 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
struct crypto_ahash *auth = ctx->auth;
struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
struct ahash_request *ahreq = (void *)(areq_ctx->tail + ictx->reqoff);
+ unsigned int flags = aead_request_flags(req) & ~mask;
u8 *hash = areq_ctx->tail;
int err;
@@ -143,7 +159,8 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
ahash_request_set_crypt(ahreq, req->dst, hash,
req->assoclen + req->cryptlen);
ahash_request_set_callback(ahreq, flags,
- authenc_geniv_ahash_done, req);
+ mask ? authenc_geniv_ahash_done2 :
+ authenc_geniv_ahash_done, req);
err = crypto_ahash_digest(ahreq);
if (err)
@@ -159,12 +176,11 @@ static void crypto_authenc_encrypt_done(void *data, int err)
{
struct aead_request *areq = data;
- if (err)
- goto out;
-
- err = crypto_authenc_genicv(areq, 0);
-
-out:
+ if (err) {
+ aead_request_complete(areq, err);
+ return;
+ }
+ err = crypto_authenc_genicv(areq, CRYPTO_TFM_REQ_MAY_SLEEP);
authenc_request_complete(areq, err);
}
@@ -199,11 +215,18 @@ static int crypto_authenc_encrypt(struct aead_request *req)
if (err)
return err;
- return crypto_authenc_genicv(req, aead_request_flags(req));
+ return crypto_authenc_genicv(req, 0);
+}
+
+static void authenc_decrypt_tail_done(void *data, int err)
+{
+ struct aead_request *req = data;
+
+ authenc_request_complete(req, err);
}
static int crypto_authenc_decrypt_tail(struct aead_request *req,
- unsigned int flags)
+ unsigned int mask)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct aead_instance *inst = aead_alg_instance(authenc);
@@ -214,6 +237,7 @@ static int crypto_authenc_decrypt_tail(struct aead_request *req,
struct skcipher_request *skreq = (void *)(areq_ctx->tail +
ictx->reqoff);
unsigned int authsize = crypto_aead_authsize(authenc);
+ unsigned int flags = aead_request_flags(req) & ~mask;
u8 *ihash = ahreq->result + authsize;
struct scatterlist *src, *dst;
@@ -230,7 +254,9 @@ static int crypto_authenc_decrypt_tail(struct aead_request *req,
skcipher_request_set_tfm(skreq, ctx->enc);
skcipher_request_set_callback(skreq, flags,
- req->base.complete, req->base.data);
+ mask ? authenc_decrypt_tail_done :
+ req->base.complete,
+ mask ? req : req->base.data);
skcipher_request_set_crypt(skreq, src, dst,
req->cryptlen - authsize, req->iv);
@@ -241,12 +267,11 @@ static void authenc_verify_ahash_done(void *data, int err)
{
struct aead_request *req = data;
- if (err)
- goto out;
-
- err = crypto_authenc_decrypt_tail(req, 0);
-
-out:
+ if (err) {
+ aead_request_complete(req, err);
+ return;
+ }
+ err = crypto_authenc_decrypt_tail(req, CRYPTO_TFM_REQ_MAY_SLEEP);
authenc_request_complete(req, err);
}
@@ -273,7 +298,7 @@ static int crypto_authenc_decrypt(struct aead_request *req)
if (err)
return err;
- return crypto_authenc_decrypt_tail(req, aead_request_flags(req));
+ return crypto_authenc_decrypt_tail(req, 0);
}
static int crypto_authenc_init_tfm(struct crypto_aead *tfm)
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
next prev parent reply other threads:[~2025-09-24 10:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20250908131642.385445532@debian4.vm>
[not found] ` <3a6b6f8f-5205-459c-810a-2425aae92fc8@linux.ibm.com>
[not found] ` <e1e420d5-dc00-14d0-fdef-635d6ef70811@redhat.com>
[not found] ` <bb68f9d6-8180-4291-9e6b-33bbdcef780f@linux.ibm.com>
[not found] ` <8cb59ed5-1c9a-49de-beee-01eda52ad618@linux.ibm.com>
[not found] ` <1af710ec-0f23-2522-d715-e683b9e557d8@redhat.com>
[not found] ` <f799d7ab97470f2529b8dcb5566fd673@linux.ibm.com>
2025-09-22 19:08 ` [PATCH] crypto/authenc: don't return -EBUSY when enqueuing the hash request Mikulas Patocka
2025-09-23 3:47 ` Herbert Xu
2025-09-23 11:14 ` Mikulas Patocka
2025-09-23 14:36 ` Mikulas Patocka
2025-09-23 15:17 ` Herbert Xu
2025-09-24 10:20 ` Herbert Xu [this message]
2025-09-24 13:17 ` [PATCH] crypto: authenc - Correctly pass EINPROGRESS back up to the caller Ingo Franzki
2025-11-25 14:02 ` [PATCH] crypto/authenc: don't return -EBUSY when enqueuing the hash request Mikulas Patocka
2025-11-26 5:16 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aNPF4bjo6FbvujIx@gondor.apana.org.au \
--to=herbert@gondor.apana.org.au \
--cc=agk@redhat.com \
--cc=davem@davemloft.net \
--cc=dengler@linux.ibm.com \
--cc=dm-devel@lists.linux.dev \
--cc=ebiggers@kernel.org \
--cc=freude@linux.ibm.com \
--cc=gmazyland@gmail.com \
--cc=ifranzki@linux.ibm.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mpatocka@redhat.com \
--cc=snitzer@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox