Thread (1 message) 1 message, 1 author, 5d ago

[PATCH] crypto: algif_skcipher - snapshot IV for async skcipher requests

From: Max Clinton <hidden>
Date: 2026-05-18 23:37:15
Also in: lkml
Subsystem: crypto api, the rest · Maintainers: Herbert Xu, "David S. Miller", Linus Torvalds

AF_ALG skcipher AIO requests currently use the socket-wide IV buffer
during request processing.  For async requests, later socket activity
can update that shared state before the original request has fully
completed, which can lead to inconsistent IV handling.

Snapshot the IV into per-request storage when preparing the skcipher
request, so in-flight operations no longer depend on mutable socket
state.

This mirrors the algif_aead fix from commit 5aa58c3a572b ("crypto:
algif_aead - snapshot IV for async AEAD requests"), which addressed
the same shape of bug in the AEAD sibling subsystem.

Tested on Debian Trixie 6.12.74+deb13+1-amd64 (unpatched) and on
v6.12.86 + this patch via virtme-ng on the same host. Reproducer
results: 10-14% race rate over 50000 iterations on the unpatched
kernel against cryptd(cbc(aes-generic)); 0 races at 50000 and
200000 iterations on the patched kernel; 0 races at 200000
iterations on the unpatched kernel with the synchronous
cbc(aes-generic) driver as a control case (confirming the race is
gated on the async dispatch path).

Fixes: e870456d8e7c ("crypto: algif_skcipher - overhaul memory management")
Cc: stable@kernel.org
Reported-by: Max Clinton <redacted>
Signed-off-by: Max Clinton <redacted>
---
 crypto/algif_skcipher.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index ba0a17fd9..519ff8d17 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -23,6 +23,7 @@
  * the RX SGL release.
  */
 
+#include <crypto/internal/skcipher.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/skcipher.h>
 #include <crypto/if_alg.h>
@@ -103,9 +104,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 	struct af_alg_ctx *ctx = ask->private;
 	struct crypto_skcipher *tfm = pask->private;
 	unsigned int bs = crypto_skcipher_chunksize(tfm);
+	unsigned int ivsize = crypto_skcipher_ivsize(tfm);
 	struct af_alg_async_req *areq;
 	unsigned cflags = 0;
 	int err = 0;
+	void *iv;
 	size_t len = 0;
 
 	if (!ctx->init || (ctx->more && ctx->used < bs)) {
@@ -116,10 +119,14 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 
 	/* Allocate cipher request for current operation. */
 	areq = af_alg_alloc_areq(sk, sizeof(struct af_alg_async_req) +
-				     crypto_skcipher_reqsize(tfm));
+				     crypto_skcipher_reqsize(tfm) + ivsize);
 	if (IS_ERR(areq))
 		return PTR_ERR(areq);
 
+	iv = (u8 *)skcipher_request_ctx(&areq->cra_u.skcipher_req) +
+	     crypto_skcipher_reqsize(tfm);
+	memcpy(iv, ctx->iv, ivsize);
+
 	/* convert iovecs of output buffers into RX SGL */
 	err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
 	if (err)
@@ -159,7 +166,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 	/* Initialize the crypto operation */
 	skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
 	skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl,
-				   areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv);
+				   areq->first_rsgl.sgl.sgt.sgl, len, iv);
 
 	if (ctx->state) {
 		err = crypto_skcipher_import(&areq->cra_u.skcipher_req,
-- 
2.47.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help