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: 37+ 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 ` [PATCH v4 01/19] dt-bindings: crypto: add Rambus CryptoManager Hub Alex Ousherovitch
2026-08-25 22:28 ` sashiko-bot
2026-08-26 17:02 ` Conor Dooley
2026-08-27 1:39 ` 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:27 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 05/19] crypto: cmh - add HMAC ahash 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: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: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: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:25 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 10/19] crypto: cmh - add ChaCha20-Poly1305 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:32 ` sashiko-bot
2026-08-25 22:15 ` [PATCH v4 12/19] crypto: cmh - add RSA akcipher Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 13/19] crypto: cmh - add ECDSA/SM2 sig Alex Ousherovitch
2026-08-25 22:15 ` [PATCH v4 14/19] crypto: cmh - add ECDH/X25519 kpp 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: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: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: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 ` [PATCH v4 19/19] MAINTAINERS: add Rambus CryptoManager Hub (CMH) 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox