DMA Engine development
 help / color / mirror / Atom feed
* [PATCH] dmaengine: tegra-adma: Fix use-after-free
@ 2025-11-10 14:24 Sheetal .
  2025-11-27  9:25 ` Thierry Reding
  2025-12-16 16:56 ` Vinod Koul
  0 siblings, 2 replies; 4+ messages in thread
From: Sheetal . @ 2025-11-10 14:24 UTC (permalink / raw)
  To: vkoul
  Cc: ldewangan, jonathanh, thierry.reding, dmaengine, linux-tegra,
	linux-kernel, Sheetal

From: Sheetal <sheetal@nvidia.com>

A use-after-free bug exists in the Tegra ADMA driver when audio streams
are terminated, particularly during XRUN conditions. The issue occurs
when the DMA buffer is freed by tegra_adma_terminate_all() before the
vchan completion tasklet finishes accessing it.

The race condition follows this sequence:

  1. DMA transfer completes, triggering an interrupt that schedules the
     completion tasklet (tasklet has not executed yet)
  2. Audio playback stops, calling tegra_adma_terminate_all() which
     frees the DMA buffer memory via kfree()
  3. The scheduled tasklet finally executes, calling vchan_complete()
     which attempts to access the already-freed memory

Since tasklets can execute at any time after being scheduled, there is
no guarantee that the buffer will remain valid when vchan_complete()
runs.

Fix this by properly synchronizing the virtual channel completion:
 - Calling vchan_terminate_vdesc() in tegra_adma_stop() to mark the
   descriptors as terminated instead of freeing the descriptor.
 - Add the callback tegra_adma_synchronize() that calls
   vchan_synchronize() which kills any pending tasklets and frees any
   terminated descriptors.

Crash logs:
[  337.427523] BUG: KASAN: use-after-free in vchan_complete+0x124/0x3b0
[  337.427544] Read of size 8 at addr ffff000132055428 by task swapper/0/0

[  337.427562] Call trace:
[  337.427564]  dump_backtrace+0x0/0x320
[  337.427571]  show_stack+0x20/0x30
[  337.427575]  dump_stack_lvl+0x68/0x84
[  337.427584]  print_address_description.constprop.0+0x74/0x2b8
[  337.427590]  kasan_report+0x1f4/0x210
[  337.427598]  __asan_load8+0xa0/0xd0
[  337.427603]  vchan_complete+0x124/0x3b0
[  337.427609]  tasklet_action_common.constprop.0+0x190/0x1d0
[  337.427617]  tasklet_action+0x30/0x40
[  337.427623]  __do_softirq+0x1a0/0x5c4
[  337.427628]  irq_exit+0x110/0x140
[  337.427633]  handle_domain_irq+0xa4/0xe0
[  337.427640]  gic_handle_irq+0x64/0x160
[  337.427644]  call_on_irq_stack+0x20/0x4c
[  337.427649]  do_interrupt_handler+0x7c/0x90
[  337.427654]  el1_interrupt+0x30/0x80
[  337.427659]  el1h_64_irq_handler+0x18/0x30
[  337.427663]  el1h_64_irq+0x7c/0x80
[  337.427667]  cpuidle_enter_state+0xe4/0x540
[  337.427674]  cpuidle_enter+0x54/0x80
[  337.427679]  do_idle+0x2e0/0x380
[  337.427685]  cpu_startup_entry+0x2c/0x70
[  337.427690]  rest_init+0x114/0x130
[  337.427695]  arch_call_rest_init+0x18/0x24
[  337.427702]  start_kernel+0x380/0x3b4
[  337.427706]  __primary_switched+0xc0/0xc8

Fixes: f46b195799b5 ("dmaengine: tegra-adma: Add support for Tegra210 ADMA")

Signed-off-by: Sheetal <sheetal@nvidia.com>
---
 drivers/dma/tegra210-adma.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index fad896ff29a2..812f64569e6d 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -429,10 +429,17 @@ static void tegra_adma_stop(struct tegra_adma_chan *tdc)
 		return;
 	}
 
-	kfree(tdc->desc);
+	vchan_terminate_vdesc(&tdc->desc->vd);
 	tdc->desc = NULL;
 }
 
+static void tegra_adma_synchronize(struct dma_chan *dc)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+
+	vchan_synchronize(&tdc->vc);
+}
+
 static void tegra_adma_start(struct tegra_adma_chan *tdc)
 {
 	struct virt_dma_desc *vd = vchan_next_desc(&tdc->vc);
@@ -1155,6 +1162,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
 	tdma->dma_dev.device_config = tegra_adma_slave_config;
 	tdma->dma_dev.device_tx_status = tegra_adma_tx_status;
 	tdma->dma_dev.device_terminate_all = tegra_adma_terminate_all;
+	tdma->dma_dev.device_synchronize = tegra_adma_synchronize;
 	tdma->dma_dev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 	tdma->dma_dev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 	tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] dmaengine: tegra-adma: Fix use-after-free
  2025-11-10 14:24 [PATCH] dmaengine: tegra-adma: Fix use-after-free Sheetal .
@ 2025-11-27  9:25 ` Thierry Reding
  2025-12-16 15:23   ` Vinod Koul
  2025-12-16 16:56 ` Vinod Koul
  1 sibling, 1 reply; 4+ messages in thread
From: Thierry Reding @ 2025-11-27  9:25 UTC (permalink / raw)
  To: Sheetal .
  Cc: vkoul, ldewangan, jonathanh, dmaengine, linux-tegra, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3283 bytes --]

On Mon, Nov 10, 2025 at 07:54:45PM +0530, Sheetal . wrote:
> From: Sheetal <sheetal@nvidia.com>
> 
> A use-after-free bug exists in the Tegra ADMA driver when audio streams
> are terminated, particularly during XRUN conditions. The issue occurs
> when the DMA buffer is freed by tegra_adma_terminate_all() before the
> vchan completion tasklet finishes accessing it.
> 
> The race condition follows this sequence:
> 
>   1. DMA transfer completes, triggering an interrupt that schedules the
>      completion tasklet (tasklet has not executed yet)
>   2. Audio playback stops, calling tegra_adma_terminate_all() which
>      frees the DMA buffer memory via kfree()
>   3. The scheduled tasklet finally executes, calling vchan_complete()
>      which attempts to access the already-freed memory
> 
> Since tasklets can execute at any time after being scheduled, there is
> no guarantee that the buffer will remain valid when vchan_complete()
> runs.
> 
> Fix this by properly synchronizing the virtual channel completion:
>  - Calling vchan_terminate_vdesc() in tegra_adma_stop() to mark the
>    descriptors as terminated instead of freeing the descriptor.
>  - Add the callback tegra_adma_synchronize() that calls
>    vchan_synchronize() which kills any pending tasklets and frees any
>    terminated descriptors.
> 
> Crash logs:
> [  337.427523] BUG: KASAN: use-after-free in vchan_complete+0x124/0x3b0
> [  337.427544] Read of size 8 at addr ffff000132055428 by task swapper/0/0
> 
> [  337.427562] Call trace:
> [  337.427564]  dump_backtrace+0x0/0x320
> [  337.427571]  show_stack+0x20/0x30
> [  337.427575]  dump_stack_lvl+0x68/0x84
> [  337.427584]  print_address_description.constprop.0+0x74/0x2b8
> [  337.427590]  kasan_report+0x1f4/0x210
> [  337.427598]  __asan_load8+0xa0/0xd0
> [  337.427603]  vchan_complete+0x124/0x3b0
> [  337.427609]  tasklet_action_common.constprop.0+0x190/0x1d0
> [  337.427617]  tasklet_action+0x30/0x40
> [  337.427623]  __do_softirq+0x1a0/0x5c4
> [  337.427628]  irq_exit+0x110/0x140
> [  337.427633]  handle_domain_irq+0xa4/0xe0
> [  337.427640]  gic_handle_irq+0x64/0x160
> [  337.427644]  call_on_irq_stack+0x20/0x4c
> [  337.427649]  do_interrupt_handler+0x7c/0x90
> [  337.427654]  el1_interrupt+0x30/0x80
> [  337.427659]  el1h_64_irq_handler+0x18/0x30
> [  337.427663]  el1h_64_irq+0x7c/0x80
> [  337.427667]  cpuidle_enter_state+0xe4/0x540
> [  337.427674]  cpuidle_enter+0x54/0x80
> [  337.427679]  do_idle+0x2e0/0x380
> [  337.427685]  cpu_startup_entry+0x2c/0x70
> [  337.427690]  rest_init+0x114/0x130
> [  337.427695]  arch_call_rest_init+0x18/0x24
> [  337.427702]  start_kernel+0x380/0x3b4
> [  337.427706]  __primary_switched+0xc0/0xc8
> 
> Fixes: f46b195799b5 ("dmaengine: tegra-adma: Add support for Tegra210 ADMA")
> 
> Signed-off-by: Sheetal <sheetal@nvidia.com>
> ---
>  drivers/dma/tegra210-adma.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)

Tiny nit-pick: there should be no blank line between the tags above
(i.e. between the Fixes: and Signed-off-by: lines).

Vinod, is that something you can fix up while applying, or do you want a
new patch for that?

In either case:

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] dmaengine: tegra-adma: Fix use-after-free
  2025-11-27  9:25 ` Thierry Reding
@ 2025-12-16 15:23   ` Vinod Koul
  0 siblings, 0 replies; 4+ messages in thread
From: Vinod Koul @ 2025-12-16 15:23 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Sheetal ., ldewangan, jonathanh, dmaengine, linux-tegra,
	linux-kernel

On 27-11-25, 10:25, Thierry Reding wrote:
> On Mon, Nov 10, 2025 at 07:54:45PM +0530, Sheetal . wrote:
> 
> Tiny nit-pick: there should be no blank line between the tags above
> (i.e. between the Fixes: and Signed-off-by: lines).
> 
> Vinod, is that something you can fix up while applying, or do you want a
> new patch for that?

Yep, fixed that

-- 
~Vinod

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] dmaengine: tegra-adma: Fix use-after-free
  2025-11-10 14:24 [PATCH] dmaengine: tegra-adma: Fix use-after-free Sheetal .
  2025-11-27  9:25 ` Thierry Reding
@ 2025-12-16 16:56 ` Vinod Koul
  1 sibling, 0 replies; 4+ messages in thread
From: Vinod Koul @ 2025-12-16 16:56 UTC (permalink / raw)
  To: Sheetal .
  Cc: ldewangan, jonathanh, thierry.reding, dmaengine, linux-tegra,
	linux-kernel


On Mon, 10 Nov 2025 19:54:45 +0530, Sheetal . wrote:
> A use-after-free bug exists in the Tegra ADMA driver when audio streams
> are terminated, particularly during XRUN conditions. The issue occurs
> when the DMA buffer is freed by tegra_adma_terminate_all() before the
> vchan completion tasklet finishes accessing it.
> 
> The race condition follows this sequence:
> 
> [...]

Applied, thanks!

[1/1] dmaengine: tegra-adma: Fix use-after-free
      commit: 2efd07a7c36949e6fa36a69183df24d368bf9e96

Best regards,
-- 
~Vinod



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-12-16 16:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-10 14:24 [PATCH] dmaengine: tegra-adma: Fix use-after-free Sheetal .
2025-11-27  9:25 ` Thierry Reding
2025-12-16 15:23   ` Vinod Koul
2025-12-16 16:56 ` Vinod Koul

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox