DMA Engine development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Daniel Byrne" <daniel1.byrne@intel.com>
Cc: dmaengine@vger.kernel.org, vkoul@kernel.org, Frank.Li@kernel.org
Subject: Re: [PATCH 14/17] dmaengine: idxd: complete an iaa_crypto descriptor through its own driver on abort and flush
Date: Mon, 19 Oct 2026 18:56:18 +0000	[thread overview]
Message-ID: <sashiko-outbox-178117@kernel.org> (raw)
In-Reply-To: <20261019150630.4026341-15-daniel1.byrne@intel.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] dmaengine: idxd: active DMA unmap and UAF in idxd_flush_pending_descs()
--

commit 17311ece6ccc1def94a5c98267c599339eae70ce
Author: Daniel Byrne <daniel1.byrne@intel.com>

dmaengine: idxd: complete an iaa_crypto descriptor through its own driver on abort and flush

This commit updates idxd_flush_pending_descs() and llist_abort_desc() to
complete or skip non-dmaengine descriptors via their own driver's completion
handler rather than treating them as dmaengine transactions, and avoids
blocking in idxd_alloc_desc() when a workqueue is permanently dying.

> diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
> index 222c201669bdd..a33c4309f5d42 100644
> --- a/drivers/dma/idxd/device.c
> +++ b/drivers/dma/idxd/device.c
> @@ -1534,10 +1534,25 @@ static void idxd_flush_pending_descs(struct idxd_irq_entry *ie,
>  		list_del(&desc->list);
>  		ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT;
>  		/*
> -		 * wq is being disabled. Any remaining descriptors are
> -		 * likely to be stuck and can be dropped. callback could
> -		 * point to code that is no longer accessible, for example
> -		 * if dmatest module has been unloaded.
> +		 * Another driver's descriptor carries that driver's request
> +		 * in place of a txd, and a client may still wait for it, so it
> +		 * goes back through that driver's completion. The completion
> +		 * reads the outcome from the record, which the device never
> +		 * wrote for an unfinished descriptor. Only a dmaengine channel
> +		 * terminates, so nothing of such a queue is quarantined.
> +		 */
> +		if (!idxd_wq_has_txd(wq)) {
> +			if (ctype == IDXD_COMPLETE_ABORT)
> +				desc->completion->status = IDXD_COMP_DESC_ABORT;
> +			idxd_desc_complete(desc, ctype, true);
> +			continue;
> +		}

[Severity: Critical]
When an iaa_crypto workqueue with in-flight interrupt-armed requests is
disabled via iaa_crypto_remove() -> idxd_drv_disable_wq(), idxd_wq_free_irq()
calls idxd_flush_pending_descs() unconditionally even if idxd_wq_drain()
timed out:

drivers/dma/idxd/device.c:idxd_drv_disable_wq() {
	...
	idxd_wq_unmap_portal(wq);
	rc = idxd_wq_drain(wq);
	idxd_wq_free_irq(wq);
	rc |= idxd_wq_reset(wq);
	...
}

If idxd_wq_drain() returns -ETIMEDOUT (either because DRAIN_WQ timed out or
because an earlier command set IDXD_FLAG_CMD_TIMEDOUT), the hardware engine is
still active and processing unfinished descriptors when
idxd_flush_pending_descs() runs.

For an unfinished descriptor (ctype == IDXD_COMPLETE_ABORT), calling
idxd_desc_complete() invokes iaa_desc_complete():

drivers/crypto/intel/iaa/iaa_crypto_main.c:iaa_desc_complete() {
	...
err:
	dma_unmap_sg(dev, ctx->req->dst, sg_nents(ctx->req->dst), DMA_FROM_DEVICE);
	iaa_unmap_src(dev, ctx->req);
out:
	if (ret != 0)
		dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);

	if (ctx->req->base.complete)
		acomp_request_complete(ctx->req, err);

	if (free_desc)
		idxd_free_desc(idxd_desc->wq, idxd_desc);
	iaa_wq_put(idxd_desc->wq);
}

Doesn't completing an unfinished descriptor here while the device is still
active cause active DMA unmapping and use-after-free? Specifically:

1. iaa_desc_complete() unmaps ctx->req->dst and ctx->req->src (and via
iaa_unmap_src() unmaps req_ctx->bounce_src_dma and frees req_ctx->bounce_src
back to iaa_bounce_pool) while the hardware engine may still be DMA-reading
src1_addr and DMA-writing dst_addr.

2. acomp_request_complete() notifies the caller, which can free or reuse the
request and scatterlist buffers while hardware DMA is still in flight.

3. iaa_wq_put() drops the iaa_wq reference. During iaa_crypto_remove(),
iaa_wq->remove is set to true, so dropping the last reference calls
__free_iaa_wq() -> free_iaa_device() -> remove_device_compression_modes() ->
free_device_compression_mode(), freeing device_mode->aecs_comp_table via
dma_free_coherent() while an in-flight compression descriptor in hardware
still reads src2_addr (aecs_comp_table_dma_addr).

4. Because iaa_desc_complete() ignores comp_type and inspects
idxd_desc->iax_completion->status via check_completion(), can a concurrent
hardware completion write between setting desc->completion->status =
IDXD_COMP_DESC_ABORT and check_completion() overwrite IDXD_COMP_DESC_ABORT
with IAX_COMP_SUCCESS or IAA_ANALYTICS_ERROR, causing iaa_desc_complete() to
treat the aborted descriptor as succeeded or retryable during teardown?

>  		/*
> -		 * wq is being disabled. Any remaining descriptors are
[ ... ]
>  		tx = &desc->txd;
>  		tx->callback = NULL;

[ ... ]

>
> -- 
> 2.51.2
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019150630.4026341-1-daniel1.byrne@intel.com?part=14

  reply	other threads:[~2026-10-19 18:56 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-19 15:06 [PATCH 00/17] [PATCH 00/17] dmaengine: idxd: fixes found by an in-kernel polling client Daniel Byrne
2026-10-19 15:06 ` [PATCH 01/17] dmaengine: idxd: don't queue EVL fault work for kernel WQs Daniel Byrne
2026-10-19 15:06 ` [PATCH 02/17] dmaengine: idxd: detach the user fault workqueue under the event log lock Daniel Byrne
2026-10-19 15:06 ` [PATCH 03/17] dmaengine: idxd: refuse a memcpy longer than the WQ max transfer size Daniel Byrne
2026-10-19 21:19   ` Frank Li
2026-10-19 15:06 ` [PATCH 04/17] dmaengine: idxd: list a new channel only once it is complete Daniel Byrne
2026-10-19 15:06 ` [PATCH 05/17] dmaengine: idxd: unbind the device driver before its work queues go away Daniel Byrne
2026-10-19 15:06 ` [PATCH 06/17] dmaengine: idxd: keep the interrupt handle across terminate_all Daniel Byrne
2026-10-19 15:06 ` [PATCH 07/17] dmaengine: idxd: bound device command waits and fail fast after a timeout Daniel Byrne
2026-10-19 17:05   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 08/17] dmaengine: idxd: compare the device disable status code whole Daniel Byrne
2026-10-19 15:06 ` [PATCH 09/17] dmaengine: idxd: quarantine terminate_all's descriptor slots until the device has drained Daniel Byrne
2026-10-19 17:26   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 10/17] dmaengine: idxd: return -ETIMEDOUT from drains and resets and leak what the device may still write Daniel Byrne
2026-10-19 17:50   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 11/17] dmaengine: idxd: disable the device before its work queues are unregistered Daniel Byrne
2026-10-19 18:09   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 12/17] dmaengine: idxd: hold device commands off while the reset re-creates its interrupts Daniel Byrne
2026-10-19 18:19   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 13/17] dmaengine: idxd: fix the double free of a descriptor whose submission failed Daniel Byrne
2026-10-19 15:06 ` [PATCH 14/17] dmaengine: idxd: complete an iaa_crypto descriptor through its own driver on abort and flush Daniel Byrne
2026-10-19 18:56   ` sashiko-bot [this message]
2026-10-19 15:06 ` [PATCH 15/17] dmaengine: idxd: flush the work queues on every halt type Daniel Byrne
2026-10-19 19:17   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 16/17] dmaengine: idxd: keep client callbacks on a halt flush and cancel resubmissions after a terminate Daniel Byrne
2026-10-19 19:36   ` sashiko-bot
2026-10-19 15:06 ` [PATCH 17/17] dmaengine: idxd: run the interrupt-handle revoke under the queue lock Daniel Byrne
2026-10-19 19:53   ` sashiko-bot
2026-10-19 19:09 ` [PATCH 00/17] [PATCH 00/17] dmaengine: idxd: fixes found by an in-kernel polling client Frank Li

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=sashiko-outbox-178117@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=daniel1.byrne@intel.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    /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