[PATCH] swiotlb: fix out-of-bounds read in swiotlb_release_slots()
From: Giorgi Kobakhia
Date: Sun Oct 25 2026 - 23:20:33 EST
When buffer is freed, swiotlb_release_slots() tries to merge it with the
following free space by reading the list value of the next slot.
if (index + nslots < ALIGN(index + 1, IO_TLB_SEGSIZE))
count = mem->slots[index + nslots].list;
else
count = 0;
If index is in the last segment of the pool and the pool size is not
multiple of IO_TLB_SEGSIZE, index + nslots becomes equal to mem->nslabs
leading to out of bound read.
BUG: KASAN: slab-out-of-bounds in swiotlb_release_slots
Read of size 2
Call trace:
swiotlb_release_slots (kernel/dma/swiotlb.c:1653)
__swiotlb_tbl_unmap_single (kernel/dma/swiotlb.c:1734)
dma_unmap_phys (./include/linux/swiotlb.h:262 kernel/dma/direct.h:102
kernel/dma/mapping.c:218)
dma_unmap_page_attrs (kernel/dma/mapping.c:236)
The commit 0b84e4f8b793 ("swiotlb: Add restricted DMA pool
initialization") makes it possible to initialize a pool with an
arbitrary size. Before it nslabs was multiple of IO_TLB_SEGSIZE and no
OOB occurred.
Add overflow check.
Fixes: 0b84e4f8b793 ("swiotlb: Add restricted DMA pool initialization")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Tested-by: Xiang Mei <xmei5@xxxxxxx>
Signed-off-by: Giorgi Kobakhia <gkobakhi@xxxxxxx>
---
kernel/dma/swiotlb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index ded7016a46a7..1f18003be343 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -1649,7 +1649,8 @@ static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr,
BUG_ON(aindex >= mem->nareas);
spin_lock_irqsave(&area->lock, flags);
- if (index + nslots < ALIGN(index + 1, IO_TLB_SEGSIZE))
+ if (index + nslots < ALIGN(index + 1, IO_TLB_SEGSIZE) &&
+ index + nslots < mem->nslabs)
count = mem->slots[index + nslots].list;
else
count = 0;
--
2.43.0