All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Hongling Zeng" <zenghongling@kylinos.cn>
Cc: Frank.Li@kernel.org, dmaengine@vger.kernel.org, vkoul@kernel.org,
	linux-sunxi@lists.linux.dev
Subject: Re: [PATCH v2] dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all
Date: Tue, 16 Jun 2026 06:16:55 +0000	[thread overview]
Message-ID: <20260616061655.CFD3B1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260616060449.42225-1-zenghongling@kylinos.cn>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Lockless read of `vchan->phy` in `sun6i_dma_terminate_all` leads to a TOCTOU race condition that can hijack and corrupt another channel's physical state.
- [High] Concurrent execution of `sun6i_dma_terminate_all` and `sun6i_dma_interrupt` can lead to a fatal NULL pointer dereference.
- [High] Terminating an active cyclic transfer frees the descriptor without clearing the virt-dma cyclic pointer, leading to a Use-After-Free.
- [High] Plain `spin_lock` on `sdev->lock` in process context deadlocks with softirq tasklet.
--

commit f08a1b576e146ed2d00cd844a90cf04a64b43397
Author: Hongling Zeng <zenghongling@kylinos.cn>

dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all

This commit addresses a memory leak for non-cyclic DMA transfers. It ensures
both cyclic and non-cyclic active descriptors are added to the desc_completed
list before cleanup to prevent them from being permanently leaked.

> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index a9a254dbf8cb9..46c837e87e6e4 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -945,16 +945,14 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
>  
>  	spin_lock_irqsave(&vchan->vc.lock, flags);

[Severity: High]
This is a pre-existing issue, but does acquiring sdev->lock earlier in this
function create a deadlock risk?

sun6i_dma_terminate_all() calls spin_lock(&sdev->lock) without disabling
softirqs. If a hardware interrupt fires on the same CPU while the lock is
held, the kernel processes pending softirqs upon returning from the interrupt.

This runs sun6i_dma_tasklet(), which attempts to acquire the lock using
spin_lock_irq(&sdev->lock). Will this cause a self-deadlock since the
interrupted process context already holds the lock?

>  
> -	if (vchan->cyclic) {
> -		vchan->cyclic = false;
> -		if (pchan && pchan->desc) {
> -			struct virt_dma_desc *vd = &pchan->desc->vd;
> -			struct virt_dma_chan *vc = &vchan->vc;
> +	if (pchan && pchan->desc && pchan->desc != pchan->done) {

[Severity: Critical]
This isn't a bug introduced by this patch, but does this code have a race
condition that can corrupt another channel?

At the top of sun6i_dma_terminate_all(), the pchan pointer is cached
locklessly from vchan->phy before taking any locks.

Concurrently, sun6i_dma_tasklet() can complete a transfer, set
vchan->phy = NULL, and reassign this exact pchan to a different virtual
channel.

When this code subsequently acquires vchan->vc.lock, wouldn't it use the
stale pchan pointer to inappropriately access descriptors and halt hardware
belonging to the newly assigned channel?

> +		struct virt_dma_desc *vd = &pchan->desc->vd;
> +		struct virt_dma_chan *vc = &vchan->vc;
>  
> -			list_add_tail(&vd->node, &vc->desc_completed);
> -		}
> +		list_add_tail(&vd->node, &vc->desc_completed);

[Severity: High]
This is a pre-existing issue, but does terminating an active cyclic transfer
leave a dangling pointer here?

The active descriptor is added to desc_completed so it can be freed by
vchan_dma_desc_free_list(), but the virt-dma pointer vc->cyclic is never
cleared.

If vchan_complete() runs asynchronously from the tasklet, couldn't it see a
non-NULL vc->cyclic and dereference the freed descriptor? Standard virt-dma
drivers typically use vchan_terminate_vdesc() to clear this.

>  	}
>  
> +	vchan->cyclic = false;
>  	vchan_get_all_descriptors(&vchan->vc, &head);
>  
>  	if (pchan) {

[ ... ]

>  		vchan->phy = NULL;
>  		pchan->vchan = NULL;
>  		pchan->desc = NULL;

[Severity: High]
This isn't a bug introduced by this patch, but can clearing pchan->desc here
race with the interrupt handler and cause a NULL pointer dereference?

In sun6i_dma_interrupt(), vchan->cyclic is read locklessly. If it evaluates
to false, the handler blocks on spin_lock(&vchan->vc.lock):

sun6i_dma_interrupt() {
    ...
    if (!vchan->cyclic) {
        spin_lock(&vchan->vc.lock);
        vchan_cookie_complete(&pchan->desc->vd);
        ...
}

If sun6i_dma_terminate_all() concurrently acquires the lock and sets
pchan->desc = NULL, when the interrupt handler unblocks, wouldn't
evaluating &pchan->desc->vd crash the kernel?

>  		pchan->done = NULL;
>  	}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616060449.42225-1-zenghongling@kylinos.cn?part=1

  reply	other threads:[~2026-06-16  6:16 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-16  6:04 [PATCH v2] dmaengine: sun6i-dma: Fix memory leak in sun6i_dma_terminate_all Hongling Zeng
2026-06-16  6:16 ` sashiko-bot [this message]
2026-06-16 16:59 ` Jernej Škrabec
2026-06-16 20:47 ` 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=20260616061655.CFD3B1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-sunxi@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    --cc=zenghongling@kylinos.cn \
    /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.