Re: [syzbot] [iommu?] KASAN: slab-use-after-free Read in free_iova

From: Jason Gunthorpe

Date: Mon Aug 10 2026 - 13:32:41 EST


On Mon, Aug 10, 2026 at 11:50:28AM +0100, Robin Murphy wrote:
> > Freed by task 5327:
> > kasan_save_stack mm/kasan/common.c:57 [inline]
> > kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
> > kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
> > poison_slab_object mm/kasan/common.c:253 [inline]
> > __kasan_slab_free+0x5c/0x80 mm/kasan/common.c:285
> > kasan_slab_free include/linux/kasan.h:235 [inline]
> > slab_free_hook mm/slub.c:2677 [inline]
> > slab_free mm/slub.c:6377 [inline]
> > kmem_cache_free+0x182/0x650 mm/slub.c:6504
> > free_iova_mem drivers/iommu/iova.c:237 [inline]
> > put_iova_domain+0xcc/0x100 drivers/iommu/iova.c:454
>
> ...except that right in between here we've called iommu_dma_free_fq() which
> would have already invoked timer_delete_sync() and freed the queue itself.
> Wut?

I've been feeding syzkaller riddles to the best AI I can get and it is
surprisingly good.. So, for this it guesses:

---
timer_delete_sync() does stop already scheduled work, but it does not
prevent a future mod_timer() from re-scheduling the now-deleted timer.

The probable sequence is:

1. A DMA unmap queues an IOVA and sets fq_timer_on = 1 at dma-iommu.c
(line 243), but has not yet executed mod_timer().

2. Concurrent PCI removal frees the device's default IOMMU
domain.

3. iommu_dma_free_fq() calls timer_delete_sync() at dma-iommu.c (line
274). Because the timer is not pending at that instant, it returns.

4. Teardown frees the flush queue and all IOVA-tree nodes through
put_iova_domain() (line 446).

5. The unmap path resumes and executes mod_timer(), rearming a timer
embedded in the soon-to-be-freed DMA cookie.

6. fq_flush_timeout() later runs and calls free_iova_fast(). It
traverses the already-destroyed IOVA rbtree, producing the reported
UAF in private_find_iova() (line 275).
---

Which seems plausible to me.. So it is a bug in a driver allowing a
dma API operation to be outstanding after it has been removed?

syzkaller console showed it did trigger a remove of a PCI function:

open("./sys/bus/pci/devices/0000:00:01.0/remove", O_WRONLY)
write(fd, "1", 1)

But I couldn't guess what device that was, if someone from syzkaller
land can clarify what they have plugged in there it might help.

The AI guessed on a GCE VM it was a display adaptor, but I don't see
how it could know that.

It would be a nice improvement to the CONFIG DMA DEBUGGING to keep
track of the driver bound state and blow up directly on all these
forbidden combinations.

Jason