From: sashiko-bot@kernel.org
To: "Alex Ousherovitch" <aousherovitch@rambus.com>
Cc: devicetree@vger.kernel.org, conor+dt@kernel.org, robh@kernel.org
Subject: Re: [PATCH v4 06/19] crypto: cmh - add CSHAKE/KMAC ahash
Date: Tue, 25 Aug 2026 22:30:47 +0000 [thread overview]
Message-ID: <20260825223048.2BDDE1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260825221539.255951-7-aousherovitch@rambus.com>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] The driver illegally maps a request context field (`rctx->checkpoint`) for DMA, which may reside on the stack, causing IOMMU faults or memory corruption.
- [High] Unbounded kernel memory leak (OOM vector) on abandoned KMAC requests because dynamically allocated chunks are orphaned onto a TFM-scoped list.
- [High] Race condition between tail holdback updates and asynchronous completion handler.
- [High] Use of spin_lock_bh() on a lock that can be acquired from hardirq context.
- [Medium] Unbounded `kmalloc` in `cmh_cshake_update` and `cmh_cshake_finup` breaks the API contract for large inputs.
- [Medium] State destruction on retryable synchronous rejection breaks the crypto API contract in cSHAKE and KMAC.
- [Medium] Defining export/import stubs for unsupported algorithms breaks testmgr initialization.
--
commit 937f2b2e4d41db65f3412cfc2efce49cf5c88cf2
Author: Alex Ousherovitch <aousherovitch@rambus.com>
crypto: cmh - add CSHAKE/KMAC ahash
Registers ahash algorithms for cSHAKE128, cSHAKE256, KMAC128, and KMAC256
using the CMH hash core. cSHAKE supports incremental update and export/import,
while KMAC has a 64KB data cap.
> diff --git a/drivers/crypto/cmh/cmh_cshake.c b/drivers/crypto/cmh/cmh_cshake.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/crypto/cmh/cmh_cshake.c
[ ... ]
> +static int cmh_cshake_update(struct ahash_request *req)
> +{
[ ... ]
> + rctx->data_buf = kmalloc(full_len, gfp | __GFP_NOWARN);
> + if (!rctx->data_buf)
> + return -ENOMEM;
[Severity: Medium]
Can this allocation fail for large inputs? The buffer size scales directly
with the unconstrained user-supplied req->nbytes, which might trigger an
unbounded allocation.
[ ... ]
> + rctx->ckpt_dma = DMA_MAPPING_ERROR;
> + if (rctx->has_checkpoint) {
> + rctx->ckpt_dma = cmh_dma_map_single(rctx->checkpoint,
> + HC_CONTEXT_SIZE,
> + DMA_TO_DEVICE);
[Severity: High]
Does this map stack memory directly for DMA?
If a caller uses AHASH_REQUEST_ON_STACK to allocate the request, mapping the
inline context field rctx->checkpoint will generate invalid physical addresses
on systems with CONFIG_VMAP_STACK enabled, causing IOMMU faults or memory
corruption.
> + if (cmh_dma_map_error(rctx->ckpt_dma)) {
> + ret = -ENOMEM;
> + goto err_unmap_save;
> + }
> + }
[ ... ]
> + ret = cmh_vcq_pack_and_submit_async(cmds, idx, rctx->packed,
> + CMH_CSHAKE_MAX_PACKED,
> + d.mbx_idx,
> + cmh_cshake_update_complete, req,
> + !!(req->base.flags &
> + CRYPTO_TFM_REQ_MAY_BACKLOG),
> + cmh_tm_async_timeout_jiffies());
> + if (ret && ret != -EBUSY)
> + goto err_unmap_ckpt;
> +
> + /*
> + * Submit accepted (in flight or backlogged) -- only now move the tail
> + * into the holdback. A synchronous rejection above (e.g. -EAGAIN)
> + * leaves rctx->buf/buf_len untouched so the caller can retry the
> + * identical update.
> + */
> + if (tail_len > 0) {
> + if (req->base.flags & CRYPTO_AHASH_REQ_VIRT)
> + memcpy(rctx->buf, req->svirt + from_src, tail_len);
> + else
> + scatterwalk_map_and_copy(rctx->buf, req->src,
> + from_src, tail_len, 0);
> + }
> + rctx->buf_len = tail_len;
[Severity: High]
Does updating the tail holdback after submitting the asynchronous hardware
command introduce a race condition?
If the hardware processing completes instantly, the callback executes and
allows the caller to submit a new request while this thread is still modifying
the holdback buffer, leading to state corruption.
> +
> + if (ret == -EBUSY)
> + return -EBUSY;
[ ... ]
> +static int cmh_cshake_submit_final(struct ahash_request *req,
> + u8 *data_buf, u32 data_len)
> +{
[ ... ]
> + rctx->ckpt_dma = DMA_MAPPING_ERROR;
> + if (rctx->has_checkpoint) {
> + rctx->ckpt_dma = cmh_dma_map_single(rctx->checkpoint,
> + HC_CONTEXT_SIZE,
> + DMA_TO_DEVICE);
[Severity: High]
Can this map a stack-allocated request context for DMA in the finalization path,
leading to the same memory corruption issue if AHASH_REQUEST_ON_STACK is used?
> + if (cmh_dma_map_error(rctx->ckpt_dma)) {
> + ret = -ENOMEM;
> + goto err_unmap_data;
> + }
> + }
[ ... ]
> +err_free_digest:
> + kfree(rctx->digest_buf);
> + rctx->digest_buf = NULL;
> +err_free_data:
> + kfree(data_buf);
> + rctx->data_buf = NULL;
> + cmh_cshake_free_reqctx(rctx);
> + return ret;
[Severity: Medium]
Does clearing has_checkpoint in this error path break the API contract?
If the hardware submission is rejected synchronously (e.g., -EAGAIN or
-ENOSPC), the caller is expected to retry, but the ability to resume on retry
has been destroyed.
> +}
[ ... ]
> +static int cmh_cshake_finup(struct ahash_request *req)
> +{
[ ... ]
> + gfp = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
> + GFP_KERNEL : GFP_ATOMIC;
> +
> + data_buf = kmalloc(data_len, gfp | __GFP_NOWARN);
> + if (!data_buf)
> + return -ENOMEM;
[Severity: Medium]
Will this unconstrained allocation fail if the caller provides a very large
input for the combined update and final transaction?
[ ... ]
> + if (req->nbytes > 0) {
> + if (req->base.flags & CRYPTO_AHASH_REQ_VIRT)
> + memcpy(data_buf + rctx->buf_len,
> + req->svirt, req->nbytes);
> + else
> + scatterwalk_map_and_copy(data_buf + rctx->buf_len,
> + req->src, 0,
> + req->nbytes, 0);
> + }
> +
> + rctx->buf_len = 0;
> + return cmh_cshake_submit_final(req, data_buf, data_len);
[Severity: Medium]
Is it safe to clear rctx->buf_len before knowing if the hardware will
accept the submission?
If cmh_cshake_submit_final() returns -EAGAIN, the caller will retry, but the
holdback tail has already been cleared.
> +}
[ ... ]
> diff --git a/drivers/crypto/cmh/cmh_kmac.c b/drivers/crypto/cmh/cmh_kmac.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/crypto/cmh/cmh_kmac.c
[ ... ]
> +static void cmh_kmac_free_chunks(struct cmh_kmac_reqctx *rctx,
> + struct cmh_kmac_tfm_ctx *tctx)
> +{
> + struct cmh_kmac_chunk *chunk, *tmp;
> +
> + spin_lock_bh(&tctx->chunk_lock);
[Severity: High]
Could using spin_lock_bh() lead to deadlocks?
The crypto ahash API can be called from a hardirq context. Because
spin_lock_bh() does not disable hardirqs, a hardware interrupt could spin
indefinitely on this lock if it attempts to acquire it while a softirq already
holds it.
> + list_for_each_entry_safe(chunk, tmp, &rctx->chunks, list) {
> + list_del(&chunk->list);
> + list_del(&chunk->tfm_node);
> + kfree(chunk);
> + }
> + spin_unlock_bh(&tctx->chunk_lock);
> + rctx->num_chunks = 0;
> + rctx->total_len = 0;
> +}
[ ... ]
> +static int cmh_kmac_init(struct ahash_request *req)
> +{
> + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
> + struct cmh_kmac_reqctx *rctx = ahash_request_ctx(req);
> +
> + rctx->info = cmh_kmac_get_info(tfm);
> + rctx->error = 0;
> + INIT_LIST_HEAD(&rctx->chunks);
[Severity: High]
Does re-initializing the request list drop tracking of previously accumulated
chunks?
If an earlier request was abandoned and not finalized properly, this leaves
the chunks orphaned in the TFM-scoped tctx->all_chunks list, creating a
memory leak.
> + rctx->num_chunks = 0;
> + rctx->total_len = 0;
> +
> + return 0;
> +}
> +
> +static int cmh_kmac_update(struct ahash_request *req)
> +{
[ ... ]
> + chunk = kmalloc(sizeof(*chunk) + req->nbytes,
> + req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
> + GFP_KERNEL : GFP_ATOMIC);
> + if (!chunk) {
> + rctx->error = -ENOMEM;
> + goto err_free_chunks;
> + }
> +
> + chunk->len = req->nbytes;
> + if (req->base.flags & CRYPTO_AHASH_REQ_VIRT) {
> + memcpy(chunk->data, req->svirt, req->nbytes);
> + } else {
> + nents = sg_nents_for_len(req->src, req->nbytes);
> + if (nents < 0 ||
> + sg_copy_to_buffer(req->src, nents,
> + chunk->data, req->nbytes) != req->nbytes) {
> + kfree(chunk);
> + rctx->error = -EINVAL;
> + goto err_free_chunks;
> + }
> + }
> +
> + list_add_tail(&chunk->list, &rctx->chunks);
> + spin_lock_bh(&tctx->chunk_lock);
> + list_add_tail(&chunk->tfm_node, &tctx->all_chunks);
> + spin_unlock_bh(&tctx->chunk_lock);
[Severity: High]
Is there an unbounded kernel memory leak here?
The chunks are dynamically allocated on the heap and tied to the TFM's lifetime
in tctx->all_chunks. If unprivileged userspace repeatedly creates and abandons
requests (e.g. by closing an AF_ALG socket early), does it continuously leak
memory until an OOM panic occurs?
> + rctx->num_chunks++;
> + rctx->total_len += req->nbytes;
> +
> + return 0;
[ ... ]
> +static int cmh_kmac_final(struct ahash_request *req)
> +{
[ ... ]
> +out_free_sg:
> + cmh_dma_free_sg(sgm);
> +
> +out_free:
> + cmh_kmac_free_chunks(rctx, tctx);
> + return ret;
[Severity: Medium]
Will this error path destroy all accumulated KMAC chunks if the hardware
submission is rejected synchronously?
This breaks the ability to retry on transient errors.
> +}
[ ... ]
> +static int cmh_kmac_export(struct ahash_request *req, void *out)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +static int cmh_kmac_import(struct ahash_request *req, const void *in)
> +{
> + return -EOPNOTSUPP;
> +}
[Severity: Medium]
Do these stub implementations cause the testmgr to fail? The testmgr expects
that if export/import function pointers are non-NULL, the feature is supported
and will try to exercise it.
[ ... ]
> +static void cmh_kmac_cra_exit(struct crypto_tfm *tfm)
> +{
> + struct cmh_kmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
> + struct cmh_kmac_chunk *chunk, *tmp;
> +
> + /* Free any orphaned chunks (e.g. testmgr export/reimport poison) */
> + spin_lock_bh(&tctx->chunk_lock);
[Severity: High]
Does acquiring this lock with spin_lock_bh() during TFM destruction present
the same deadlock risk if hardirq accesses are possible?
> + list_for_each_entry_safe(chunk, tmp, &tctx->all_chunks, tfm_node) {
> + list_del(&chunk->tfm_node);
> + kfree(chunk);
> + }
> + spin_unlock_bh(&tctx->chunk_lock);
[Severity: High]
Is doing this sweep only at TFM teardown what permits the unbounded memory
growth during the TFM's lifetime for abandoned requests?
[ ... ]
> + for (i = 0; i < CMH_KMAC_ALG_COUNT; i++) {
> + const struct cmh_kmac_alg_info *info =
> + &cmh_kmac_algs_info[i];
> + struct cmh_kmac_alg_drv *drv = &cmh_kmac_drvs[i];
> + struct ahash_alg *alg = &drv->alg;
> +
> + drv->info = info;
> +
> + alg->init = cmh_kmac_init;
> + alg->update = cmh_kmac_update;
> + alg->final = cmh_kmac_final;
> + alg->finup = cmh_kmac_finup;
> + alg->digest = cmh_kmac_digest;
> + alg->export = cmh_kmac_export;
> + alg->import = cmh_kmac_import;
[Severity: Medium]
Is it problematic to expose these stubs to the crypto API by assigning them
here? The unsupported export/import will cause testmgr initialization to fail.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260825221539.255951-1-aousherovitch@rambus.com?part=6
next prev parent reply other threads:[~2026-08-25 22:30 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 22:15 [PATCH v4 00/19] crypto: cmh - add Rambus CryptoManager Hub driver Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 01/19] dt-bindings: crypto: add Rambus CryptoManager Hub Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:28 ` sashiko-bot
2026-08-26 17:02 ` Conor Dooley
2026-08-26 17:02 ` Conor Dooley
2026-08-27 1:39 ` Ousherovitch, Alex
2026-08-27 1:39 ` Ousherovitch, Alex
2026-08-27 17:14 ` Conor Dooley
2026-08-27 17:14 ` Conor Dooley
2026-08-27 18:21 ` Ousherovitch, Alex
2026-08-27 18:21 ` Ousherovitch, Alex
2026-08-25 22:15 ` [PATCH v4 02/19] crypto: cmh - add core platform driver Alex Ousherovitch
2026-08-25 22:34 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 03/19] crypto: cmh - add key provisioning and management Alex Ousherovitch
2026-08-25 22:30 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 04/19] crypto: cmh - add SHA-2/SHA-3/SHAKE ahash Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:27 ` sashiko-bot
2026-09-11 4:31 ` Herbert Xu
2026-09-11 4:31 ` Herbert Xu
2026-09-11 21:29 ` Ousherovitch, Alex
2026-09-11 21:29 ` Ousherovitch, Alex
2026-08-25 22:15 ` [PATCH v4 05/19] crypto: cmh - add HMAC ahash Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:30 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 06/19] crypto: cmh - add CSHAKE/KMAC ahash Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:30 ` sashiko-bot [this message]
2026-08-25 22:15 ` [PATCH v4 07/19] crypto: cmh - add SM3 ahash Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:28 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 08/19] crypto: cmh - add AES skcipher/aead/cmac Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:28 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 09/19] crypto: cmh - add SM4 skcipher/aead/cmac/xcbc Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:25 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 10/19] crypto: cmh - add ChaCha20-Poly1305 Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:30 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 11/19] crypto: cmh - add DRBG hwrng Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:32 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 12/19] crypto: cmh - add RSA akcipher Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 13/19] crypto: cmh - add ECDSA/SM2 sig Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 14/19] crypto: cmh - add ECDH/X25519 kpp Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:41 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 15/19] crypto: cmh - add ML-KEM/ML-DSA (QSE) Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:36 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 16/19] crypto: cmh - add SLH-DSA/LMS/XMSS (HCQ) Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:37 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 17/19] Documentation: ioctl: add CMH ioctl documentation and register 'J' Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:34 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 18/19] selftests: crypto: cmh - add kselftest for management ioctl Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 19/19] MAINTAINERS: add Rambus CryptoManager Hub (CMH) Alex Ousherovitch
2026-08-25 22:15 ` Alex Ousherovitch
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=20260825223048.2BDDE1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=aousherovitch@rambus.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.