Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH 1/3] crypto: caam: Fix DMA mapping leak in the cbc(paes) job path
@ 2026-07-26  8:15 Richard Weinberger
  2026-07-26  8:15 ` [PATCH 2/3] crypto: caam: Map the paes protected key once per tfm Richard Weinberger
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Richard Weinberger @ 2026-07-26  8:15 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-crypto, davem, herbert, gaurav.jain, pankaj.gupta,
	horia.geanta, ebiggers, upstream+linux, Richard Weinberger

For a protected key, init_skcipher_job() maps the second job descriptor
so that the blob decapsulation descriptor can jump to it, but keeps the
address in a local variable. Nothing can ever unmap it, and the buffer
it covers lives in edesc, which skcipher_crypt_done() frees while the
mapping is still live. The mapping error is not checked either.

cbc(paes) is reachable through AF_ALG, so an unprivileged process leaks
one mapping per request, exhausting IOVA space or swiotlb buffers.

Store the mapping in the extended descriptor, release it in
skcipher_unmap() and propagate mapping failures to the caller.

Assisted-by: Claude-Code:claude-fable-5
Reported-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Richard Weinberger <richard@nod.at>
---
 drivers/crypto/caam/caamalg.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index ddbd60cf3..c83d28509 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -983,6 +983,9 @@ struct aead_edesc {
  * @sec4_sg_bytes: length of dma mapped sec4_sg space
  * @bklog: stored to determine if the request needs backlog
  * @sec4_sg_dma: bus physical mapped address of h/w link table
+ * @desc_dma: bus physical mapped address of the cipher job descriptor the
+ *	      blob decapsulation descriptor jumps to (protected key only)
+ * @desc_dma_bytes: length of the mapping at @desc_dma
  * @sec4_sg: pointer to h/w link table
  * @hw_desc: the h/w job descriptor followed by any referenced link tables
  *	     and IV
@@ -996,6 +999,8 @@ struct skcipher_edesc {
 	int sec4_sg_bytes;
 	bool bklog;
 	dma_addr_t sec4_sg_dma;
+	dma_addr_t desc_dma;
+	unsigned int desc_dma_bytes;
 	struct sec4_sg_entry *sec4_sg;
 	u32 hw_desc[];
 };
@@ -1037,6 +1042,10 @@ static void skcipher_unmap(struct device *dev, struct skcipher_edesc *edesc,
 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
 	int ivsize = crypto_skcipher_ivsize(skcipher);
 
+	if (edesc->desc_dma)
+		dma_unmap_single(dev, edesc->desc_dma, edesc->desc_dma_bytes,
+				 DMA_TO_DEVICE);
+
 	caam_unmap(dev, req->src, req->dst,
 		   edesc->src_nents, edesc->dst_nents,
 		   edesc->iv_dma, ivsize,
@@ -1313,9 +1322,9 @@ static void init_authenc_job(struct aead_request *req,
 /*
  * Fill in skcipher job descriptor
  */
-static void init_skcipher_job(struct skcipher_request *req,
-			      struct skcipher_edesc *edesc,
-			      const bool encrypt)
+static int init_skcipher_job(struct skcipher_request *req,
+			     struct skcipher_edesc *edesc,
+			     const bool encrypt)
 {
 	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
 	struct caam_ctx *ctx = crypto_skcipher_ctx_dma(skcipher);
@@ -1365,6 +1374,13 @@ static void init_skcipher_job(struct skcipher_request *req,
 					    ivsize, encrypt);
 
 		desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
+		if (dma_mapping_error(jrdev, desc_dma)) {
+			dev_err(jrdev, "unable to map cipher job descriptor\n");
+			return -ENOMEM;
+		}
+
+		edesc->desc_dma = desc_dma;
+		edesc->desc_dma_bytes = desc_bytes(desc);
 
 		cnstr_desc_protected_blob_decap(edesc->hw_desc, &ctx->cdata, desc_dma);
 	} else {
@@ -1377,6 +1393,8 @@ static void init_skcipher_job(struct skcipher_request *req,
 
 		append_seq_out_ptr(desc, dst_dma, req->cryptlen + ivsize, out_options);
 	}
+
+	return 0;
 }
 
 /*
@@ -1933,7 +1951,12 @@ static inline int skcipher_crypt(struct skcipher_request *req, bool encrypt)
 		return PTR_ERR(edesc);
 
 	/* Create and submit job descriptor*/
-	init_skcipher_job(req, edesc, encrypt);
+	ret = init_skcipher_job(req, edesc, encrypt);
+	if (ret) {
+		skcipher_unmap(jrdev, edesc, req);
+		kfree(edesc);
+		return ret;
+	}
 
 	print_hex_dump_debug("skcipher jobdesc@" __stringify(__LINE__)": ",
 			     DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-30  7:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-26  8:15 [PATCH 1/3] crypto: caam: Fix DMA mapping leak in the cbc(paes) job path Richard Weinberger
2026-07-26  8:15 ` [PATCH 2/3] crypto: caam: Map the paes protected key once per tfm Richard Weinberger
2026-07-26  8:15 ` [PATCH 3/3] crypto: caam: Validate the protected key header in setkey Richard Weinberger
2026-07-30  7:25 ` [PATCH 1/3] crypto: caam: Fix DMA mapping leak in the cbc(paes) job path Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox