Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Pavitrakumar Managutte" <pavitrakumarm@vayavyalabs.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v16 2/4] crypto: spacc - Add SPAcc ahash support
Date: Tue, 07 Jul 2026 13:13:14 +0000	[thread overview]
Message-ID: <20260707131315.5BDD91F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260707125311.2398031-3-pavitrakumarm@vayavyalabs.com>

Thank you for your contribution! Sashiko AI review found 15 potential issue(s) to consider:
- [Critical] Missing CRYPTO_ALG_NEED_FALLBACK flag for non-MAC hashes causes use-after-free and stack overflows in software fallback paths.
- [High] wait_event_interruptible() falls back to wait_event() on signal, causing a permanent hang.
- [High] Queue pointer `jb_tail` is rewound to a stale value after dropping the spinlock, causing queue corruption.
- [High] Incorrect device teardown ordering causes deadlocks, Use-After-Free, and DMA corruption.
- [High] Concurrent `setkey()` temporarily nullifies `tctx->dev`, risking a NULL pointer dereference in DMA cleanup.
- [High] Error handling in `spacc_pop_packets_ex` aborts the hardware FIFO processing loop, leaking completions.
- [High] `spacc_sg_to_ddt` maps the entire scatterlist chain ignoring `req->nbytes`, leading to IOMMU resource exhaustion.
- [High] Hardware maximum message length is unchecked, leading to silent truncation and incorrect hashes.
- [High] Monotonic `job_next_swid` assignment wraps around and overwrites active job tracking structures.
- [High] Incorrect use of I/O accessors causes byte-swapping on big-endian systems when writing to the device context.
- [High] Exhaustion of hardware contexts permanently deadlocks the single global crypto engine kworker.
- [High] Exporting hash state blindly copies 512 bytes, leaking uninitialized kernel memory.
- [Medium] `spacc_hash_do_one_request` mixes goto-based error handling with `guard()` declarations, violating cleanup rules.
- [Medium] CRYPTO_ALG_OPTIONAL_KEY is erroneously set for HMAC algorithms, bypassing mandatory key enforcement.
- [Medium] Data race on `spacc->wdcnt` between the interrupt handler and the workqueue.
--

--- Patch [2]: [PATCH v16 2/4] crypto: spacc - Add SPAcc ahash support ---
commit 9b37a1ea0e79e785bc1e2213daaf06064d34b667
Author: Pavitrakumar Managutte <pavitrakumarm@vayavyalabs.com>

crypto: spacc - Add SPAcc ahash support

Add ahash support to SPAcc driver.
Below are the hash algos supported:
- cmac(aes), xcbc(aes), cmac(sm4), xcbc(sm4), hmac(md5), md5, hmac(sha1),
  sha1, sha224, sha256, sha384, sha512, hmac(sha224), hmac(sha256),
  hmac(sha384), hmac(sha512), sha3-224, sha3-256, sha3-384, sha3-512

> diff --git a/drivers/crypto/dwc-spacc/spacc_ahash.c b/drivers/crypto/dwc-spacc/spacc_ahash.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_ahash.c
> @@ -76,22 +76,22 @@
>  static void spacc_hash_cleanup_dma_src(struct spacc_crypto_ctx *tctx,
>  				       struct ahash_request *req)
>  {
>  	struct spacc_crypto_reqctx *ctx = ahash_request_ctx(req);
>  
>  	if (tctx->tmp_sgl && tctx->tmp_sgl[0].length != 0) {
>  		dma_unmap_sg(tctx->dev, tctx->tmp_sgl, ctx->src_nents,
>  			     DMA_TO_DEVICE);
>  		kfree(tctx->tmp_sgl_buff);
>  		tctx->tmp_sgl_buff = NULL;
>  		tctx->tmp_sgl[0].length = 0;
>  	} else
>  		dma_unmap_sg(tctx->dev, req->src, ctx->src_nents,
>  			     DMA_TO_DEVICE);

[Severity: High]
Could this lead to a NULL pointer dereference regression? In
spacc_hash_cleanup_dma_src, tctx->dev is read locklessly during request
completion. If this coincides with spacc_hash_setkey, which momentarily
sets tctx->dev to NULL under a lock, the DMA unmap path might attempt
to unmap using a NULL device.

[ ... ]

> @@ -231,18 +231,18 @@
>  	tctx->tmp_sgl[0].length = 0;
>  
>  	{
>  		guard(mutex)(&tctx->lock);
>  
>  		if (tctx->handle < 0 || !tctx->ctx_valid) {
>  			/*
>  			 * spacc_open() acquires ctx_sem which may sleep;
>  			 * do_one_request runs in the crypto_engine workqueue
>  			 * which is a sleepable context, so this is safe.
>  			 */
>  			tctx->handle = spacc_open(&priv->spacc,
>  					CRYPTO_MODE_NULL, salg->mode->id,
>  					-1, 0, spacc_digest_cb, reqtfm);
>  			if (tctx->handle < 0) {
>  				dev_dbg(salg->dev,
>  					"context open failed, fallback\n");
>  				goto fallback;
>  			}

[Severity: Medium]
Is it safe to mix goto-based error handling with guard() declarations in
spacc_hash_do_one_request? This combination can create ambiguous lock
ownership release paths, violating the cleanup subsystem conventions.

[ ... ]

> @@ -307,13 +307,13 @@
>  			dev_dbg(salg->dev,
>  				"DMA init failed (%d), falling back\n", rc);
>  			goto fallback;
>  		}
>  	}
>  	rc = spacc_packet_enqueue_ddt(&priv->spacc, ctx->acb.new_handle,
>  			&ctx->src, &ctx->dst, req->nbytes,
>  			0, req->nbytes, 0, 0, 0);

[Severity: High]
Might this introduce a data corruption regression? The variable req->nbytes
is directly passed to the hardware without validating against
spacc->config.max_msg_size. Oversized requests might be silently truncated
when written to the 32-bit SPACC_REG_PROC_LEN register in
spacc_packet_enqueue_ddt_ex, which would produce invalid hash digests
without an error.

[ ... ]

> @@ -348,11 +348,11 @@
>  			rc = crypto_shash_final(desc, req->result);
>  
>  		shash_desc_zero(desc);
>  	} else {
>  		HASH_FBREQ_ON_STACK(fbreq, req);
>  
>  		rc = crypto_ahash_digest(fbreq);
>  
>  		HASH_REQUEST_ZERO(fbreq);
>  	}

[Severity: Critical]
Will this sequence cause a use-after-free regression and stack overflow?
When DMA fails, the stack-allocated fbreq is enqueued asynchronously. If
CRYPTO_ALG_NEED_FALLBACK is omitted for non-MAC hashes, the fallback TFM is
uninitialized. The asynchronous crypto engine might execute this after the
stack frame is gone, resulting in severe memory corruption.

[ ... ]

> @@ -558,9 +558,9 @@
>  static int spacc_hash_export(struct ahash_request *req, void *out)
>  {
>  	struct spacc_crypto_reqctx *ctx = ahash_request_ctx(req);
>  
>  	memcpy(out, ctx->state_buffer, HASH_MAX_STATESIZE);
>  	return 0;
>  }

[Severity: High]
Does exporting the hash state leak uninitialized kernel memory?
The function spacc_hash_export statically copies HASH_MAX_STATESIZE
(512 bytes) from the request context. Since the underlying fallback
algorithms only initialize a fraction of this structure, this might leak
uninitialized heap data to userspace.

[ ... ]

> @@ -835,16 +835,16 @@
>  	if (salg->mode->id == CRYPTO_MODE_MAC_CMAC ||
>  			salg->mode->id == CRYPTO_MODE_MAC_XCBC ||
>  			salg->mode->id == CRYPTO_MODE_MAC_SM4_CMAC ||
>  			salg->mode->id == CRYPTO_MODE_MAC_SM4_XCBC) {
>  		salg->alg.hash.base.halg.base.cra_flags =
>  			CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC |
>  			CRYPTO_ALG_NO_FALLBACK;
>  	} else {
>  		salg->alg.hash.base.halg.base.cra_flags =
>  			CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC |
>  			CRYPTO_ALG_OPTIONAL_KEY;
>  	}

[Severity: Critical]
Does the omission of the CRYPTO_ALG_NEED_FALLBACK flag for non-MAC hashes
lead to the aforementioned stack overflow regression?

[Severity: Medium]
Could applying CRYPTO_ALG_OPTIONAL_KEY to HMAC algorithms bypass mandatory
key enforcement? This omits the CRYPTO_TFM_NEED_KEY constraint, permitting
execution with uninitialized state and yielding deterministic but meaningless
MACs instead of returning -ENOKEY.

> diff --git a/drivers/crypto/dwc-spacc/spacc_core.c b/drivers/crypto/dwc-spacc/spacc_core.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_core.c
> @@ -115,11 +115,11 @@
>  
>  	nents = dma_map_sg(dev, sg, orig_nents, dma_direction);
>  	if (nents <= 0)
>  		return -ENOMEM;

[Severity: High]
Does this mapping exhaust IOMMU resources? The operation unconditionally
traverses and maps the full scatterlist chain derived from orig_nents in
spacc_sg_to_ddt, instead of limiting the mapped segments to the requested
payload length defined by req->nbytes.

[ ... ]

> @@ -445,11 +445,11 @@
>  			err = spacc_packet_enqueue_ddt(spacc, handle, &ddt, &ddt, 48,
>  					       0, 0, 0, 0, 0);
>  		if (err != 0)
>  			goto xcbc_err;
>  
>  		if (wait_event_interruptible(job->waitq, job->job_done))
>  			wait_event(job->waitq, job->job_done);

[Severity: High]
Can this fallback sleeper hang indefinitely? If wait_event_interruptible
is interrupted, it falls back to wait_event in TASK_UNINTERRUPTIBLE
state. The completion handler in spacc_pop_packets_ex only uses
wake_up_interruptible, which exclusively wakes TASK_INTERRUPTIBLE tasks,
leaving this sleeper stranded.

[ ... ]

> @@ -668,11 +668,11 @@
>  	struct spacc_device *spacc = &priv->spacc;
>  
>  	/*
>  	 * Decrement the WD CNT here since
>  	 * now we're actually going to respond
>  	 * to the IRQ completely
>  	 */
>  	if (spacc->wdcnt)
>  		--(spacc->wdcnt);

[Severity: Medium]
Is there a data race on spacc->wdcnt here? The counter is incremented under
a lock inside the IRQ handler, but spacc_pop_jobs executes a
read-modify-write decrement asynchronously without lock protection.
This might cause lost increments that break the watchdog logic.

[ ... ]

> @@ -841,12 +841,12 @@
>  	const struct hash_config *hash_cfg = NULL;
>  	unsigned long flags;
>  
>  	if (ctxid == -1) {
>  		if (down_interruptible(&spacc->ctx_sem)) {
>  			dev_dbg(spacc->dptr, "ERR: Interrupted by signal\n");
>  			return -ERESTARTSYS;
>  		}
>  	}

[Severity: High]
Does acquiring this sleepable semaphore without a timeout cause a permanent
deadlock in the global crypto engine kworker? If active TFMs outnumber
hardware contexts, the engine worker sleeps indefinitely within
do_one_request, which would stall all subsequent operations for all
hardware engines.

[ ... ]

> @@ -1313,11 +1313,11 @@
>  	if (job->first_use) {
>  		writel(job->ckey_sz | SPACC_SET_KEY_CTX(job->ctx_idx),
>  		       spacc->regmap + SPACC_REG_KEY_SZ);
>  		writel(job->hkey_sz | SPACC_SET_KEY_CTX(job->ctx_idx),
>  		       spacc->regmap + SPACC_REG_KEY_SZ);
>  	}
>  
>  	job->job_swid = spacc->job_next_swid;
>  	spacc->job_lookup[job->job_swid] = job_idx;
>  	spacc->job_next_swid = (spacc->job_next_swid + 1) % SPACC_MAX_JOBS;

[Severity: High]
Can the monotonic job_next_swid wrap around and overwrite active job
tracking structures? If the global job_next_swid wraps completely while
older, low-priority jobs remain active, it looks like it blindly
overwrites the job_lookup table and disassociates the active hardware job
from its software tracking context.

> diff --git a/drivers/crypto/dwc-spacc/spacc_device.c b/drivers/crypto/dwc-spacc/spacc_device.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_device.c
> @@ -218,12 +218,12 @@
>  
>  	/*
>  	 * Unregister the (possibly shared) IRQ first so no *new* work can
>  	 * be queued onto spacc_wq from this point on.
>  	 */
>  	devm_free_irq(&pdev->dev, priv->irq, &pdev->dev);
>  
>  	if (priv->spacc_wq)
>  		destroy_workqueue(priv->spacc_wq);
>  
>  	spacc_unregister_algs(priv);
>  
>  	if (priv->engine)
>  		crypto_engine_exit(priv->engine);

[Severity: High]
Does this teardown sequence introduce deadlocks and use-after-free
regressions? Freeing the workqueue, DMA pools, and algorithms before
terminating the active crypto engine might force in-flight asynchronous
requests to execute against destroyed memory structures. Active TFMs
outliving device unbinding may also cause memory corruption during
spacc_hash_exit_tfm.

> diff --git a/drivers/crypto/dwc-spacc/spacc_hal.c b/drivers/crypto/dwc-spacc/spacc_hal.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_hal.c
> @@ -155,10 +155,10 @@
>  	u32 __iomem *addr = addr_;
>  
>  	while (nword--) {
>  		/*
>  		 * src may be unaligned; read it as a defined little-endian
>  		 * word, then write the raw value (__raw_writel does not
>  		 * byte-swap) so the device sees the bytes in buffer order
>  		 * regardless of CPU endianness.
>  		 */
>  		__raw_writel((__force u32)get_unaligned_le32(src), addr);

[Severity: High]
Will this combination of get_unaligned_le32 and __raw_writel corrupt
the byte stream on big-endian architectures? The function
get_unaligned_le32 converts memory to host-endian, which __raw_writel
then writes without byte-swapping, reversing the byte sequence of
the context stream instead of preserving the memory layout.

> diff --git a/drivers/crypto/dwc-spacc/spacc_interrupt.c b/drivers/crypto/dwc-spacc/spacc_interrupt.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_interrupt.c
> @@ -35,11 +35,11 @@
>  			/* write the pop register to get the next job */
>  			writel(1, spacc->regmap + SPACC_REG_STAT_POP);
>  			cmdstat = readl(spacc->regmap + SPACC_REG_STATUS);
>  
>  			swid = SPACC_STATUS_SW_ID_GET(cmdstat);
>  
>  			if (swid >= SPACC_MAX_JOBS) {
>  				ret = -EIO;
>  				goto ERR;
>  			}

[Severity: High]
Does this error path prematurely abort the hardware FIFO processing loop?
Encountering a single invalid swid triggers a goto that entirely breaks out
of the STAT FIFO polling loop in spacc_pop_packets_ex. With the IRQ already
cleared, this strands the remaining completed jobs in the hardware FIFO.

[ ... ]

> @@ -91,10 +91,10 @@
>  
>  			job->job_err = ret;
>  
>  			if (spacc->autodetect) {
>  				job->job_done = 1;
>  				wake_up_interruptible(&job->waitq);
>  			}

[Severity: High]
As mentioned earlier, wait_event_interruptible can fall back to
wait_event in TASK_UNINTERRUPTIBLE. This wake_up_interruptible
will fail to wake that sleeper, leading to a permanent hang.

> diff --git a/drivers/crypto/dwc-spacc/spacc_manager.c b/drivers/crypto/dwc-spacc/spacc_manager.c
> --- /dev/null
> +++ b/drivers/crypto/dwc-spacc/spacc_manager.c
> @@ -265,10 +265,10 @@
>  					job->job_done = 1;
>  					wake_up_interruptible(&job->waitq);
>  				}
>  			}
>  		}
>  
>  		tail++;
>  		if (tail == SPACC_MAX_JOB_BUFFERS)
>  			tail = 0;
>  
>  		spacc->jb_tail = tail;

[Severity: High]
Does this logic cause queue corruption and lost jobs? The function
spacc_process_jb caches jb_tail, drops the spinlock to execute a
callback, and then blindly restores the cached value upon reacquiring the
lock. This appears to unconditionally overwrite any concurrent queue
advancements.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260707125311.2398031-1-pavitrakumarm@vayavyalabs.com?part=2

  reply	other threads:[~2026-07-07 13:13 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07 12:53 [PATCH v16 0/4] crypto: spacc - Add SPAcc Crypto Driver Pavitrakumar Managutte
2026-07-07 12:53 ` [PATCH v16 1/4] dt-bindings: crypto: Document support for SPAcc Pavitrakumar Managutte
2026-07-07 12:53 ` [PATCH v16 2/4] crypto: spacc - Add SPAcc ahash support Pavitrakumar Managutte
2026-07-07 13:13   ` sashiko-bot [this message]
2026-07-07 12:53 ` [PATCH v16 3/4] crypto: spacc - Add SPAcc AUTODETECT Support Pavitrakumar Managutte
2026-07-07 13:09   ` sashiko-bot
2026-07-07 12:53 ` [PATCH v16 4/4] crypto: spacc - Add SPAcc Kconfig and Makefile Pavitrakumar Managutte
2026-07-07 13:06   ` sashiko-bot
2026-07-10 12:27   ` Julian Braha

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=20260707131315.5BDD91F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=pavitrakumarm@vayavyalabs.com \
    --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