[PATCH 3/5] dma: swiotlb: Remove default pool from the pools list on exit

From: Marek Szyprowski

Date: Mon Oct 26 2026 - 06:02:49 EST


With CONFIG_SWIOTLB_DYNAMIC enabled, the default memory pool is added to
the io_tlb_default_mem.pools RCU list during initialization. When an IOMMU
takes over DMA translation, swiotlb_exit() tears the default pool down and
clears it with memset(), but leaves its node on the pools list. The list
then contains a zeroed entry with a NULL next pointer, and any later walk
of the list, for example mem_used() when reading the io_tlb_used debugfs
file, dereferences an invalid pointer and crashes.

Remove the default pool from the list before freeing it, and wait for an
RCU grace period before clearing it, so that no reader can still see it.

Fixes: 1aaa736815eb ("swiotlb: allocate a new memory pool when existing pools are full")
Closes: https://sashiko.dev/#/bug/linux-f75998aa-65ea-4596-9bb4-fa83773012a3
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
---
kernel/dma/swiotlb.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index db731f7891b7..51fb2d34f6f2 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -665,6 +665,12 @@ void __init swiotlb_exit(void)
return;

pr_info("tearing down default memory pool\n");
+#ifdef CONFIG_SWIOTLB_DYNAMIC
+ spin_lock(&io_tlb_default_mem.lock);
+ list_del_rcu(&mem->node);
+ spin_unlock(&io_tlb_default_mem.lock);
+ synchronize_rcu();
+#endif
tbl_vaddr = (unsigned long)phys_to_virt(mem->start);
tbl_size = PAGE_ALIGN(mem->end - mem->start);
slots_size = PAGE_ALIGN(array_size(sizeof(*mem->slots), mem->nslabs));
--
2.43.0