[PATCH] iommu/iova: Clear the slab cache pointers when destroying them

Davidlohr Bueso posted 1 patch 1 week ago
drivers/iommu/iova.c | 4 ++++
1 file changed, 4 insertions(+)
[PATCH] iommu/iova: Clear the slab cache pointers when destroying them
Posted by Davidlohr Bueso 1 week ago
Both iova_cache_get() failure path and iova_cache_put() destroy the two
slab caches without clearing the pointers, leaving them dangling with
iova_cache_users at zero. The next iova_cache_get() then re-enters the
respective block, and if it fails early enough to reach 'out_err' before
re-creating both caches, it calls kmem_cache_destroy() a second time on
whichever cache is still stale:

  BUG: KASAN: slab-use-after-free in iova_cache_get+0x216/0x280
  Read of size 1 at addr ffff888001b9fdc0 by task swapper/0/1
  CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.2.0-rc1 #2
  Call Trace:
   <TASK>
   dump_stack_lvl+0x53/0x70
   print_report+0xce/0x620
   kasan_report+0xce/0x100
   __kasan_check_byte+0x36/0x50
   kmem_cache_destroy+0x1b/0x1c0
   iova_cache_get+0x216/0x280
   ...
  Freed by task 1:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   kasan_save_free_info+0x3b/0x60
   __kasan_slab_free+0x43/0x70
   kmem_cache_free+0xbe/0x3c0
   kobject_put+0x14d/0x280
   iova_cache_put+0x8e/0xd0

Clear both pointers after destroying them, in both places.

Fixes: 84e6f56be9c6 ("iommu/iova: use named kmem_cache for iova magazines")
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 drivers/iommu/iova.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index b710e5ad37e2..0e8ea04b824f 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -984,6 +984,8 @@ int iova_cache_get(void)
 out_err:
 	kmem_cache_destroy(iova_cache);
 	kmem_cache_destroy(iova_magazine_cache);
+	iova_cache = NULL;
+	iova_magazine_cache = NULL;
 	mutex_unlock(&iova_cache_mutex);
 	return err;
 }
@@ -1001,6 +1003,8 @@ void iova_cache_put(void)
 		cpuhp_remove_multi_state(CPUHP_IOMMU_IOVA_DEAD);
 		kmem_cache_destroy(iova_cache);
 		kmem_cache_destroy(iova_magazine_cache);
+		iova_cache = NULL;
+		iova_magazine_cache = NULL;
 	}
 	mutex_unlock(&iova_cache_mutex);
 }
-- 
2.39.5
Re: [PATCH] iommu/iova: Clear the slab cache pointers when destroying them
Posted by Robin Murphy 6 days, 13 hours ago
On 16/08/2026 7:43 pm, Davidlohr Bueso wrote:
> Both iova_cache_get() failure path and iova_cache_put() destroy the two
> slab caches without clearing the pointers, leaving them dangling with
> iova_cache_users at zero. The next iova_cache_get() then re-enters the
> respective block, and if it fails early enough to reach 'out_err' before
> re-creating both caches, it calls kmem_cache_destroy() a second time on
> whichever cache is still stale:
> 
>    BUG: KASAN: slab-use-after-free in iova_cache_get+0x216/0x280
>    Read of size 1 at addr ffff888001b9fdc0 by task swapper/0/1
>    CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.2.0-rc1 #2
>    Call Trace:
>     <TASK>
>     dump_stack_lvl+0x53/0x70
>     print_report+0xce/0x620
>     kasan_report+0xce/0x100
>     __kasan_check_byte+0x36/0x50
>     kmem_cache_destroy+0x1b/0x1c0
>     iova_cache_get+0x216/0x280
>     ...
>    Freed by task 1:
>     kasan_save_stack+0x33/0x60
>     kasan_save_track+0x14/0x30
>     kasan_save_free_info+0x3b/0x60
>     __kasan_slab_free+0x43/0x70
>     kmem_cache_free+0xbe/0x3c0
>     kobject_put+0x14d/0x280
>     iova_cache_put+0x8e/0xd0
> 
> Clear both pointers after destroying them, in both places.

Out of curiosity, what architecture/kernel config have you found this 
with? I see the logic, but off the top of my head I'm somewhat 
struggling to imagine the scenario in which iova_cache_get() succeeds, 
the last user (so no iommu-dma) cleanly calls iova_cache_put() to be 
able to free the state, then another iova_cache_get() fails. Is 
everything else also falling apart in flames anyway at this point?

Thanks,
Robin.

> Fixes: 84e6f56be9c6 ("iommu/iova: use named kmem_cache for iova magazines")
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
> ---
>   drivers/iommu/iova.c | 4 ++++
>   1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
> index b710e5ad37e2..0e8ea04b824f 100644
> --- a/drivers/iommu/iova.c
> +++ b/drivers/iommu/iova.c
> @@ -984,6 +984,8 @@ int iova_cache_get(void)
>   out_err:
>   	kmem_cache_destroy(iova_cache);
>   	kmem_cache_destroy(iova_magazine_cache);
> +	iova_cache = NULL;
> +	iova_magazine_cache = NULL;
>   	mutex_unlock(&iova_cache_mutex);
>   	return err;
>   }
> @@ -1001,6 +1003,8 @@ void iova_cache_put(void)
>   		cpuhp_remove_multi_state(CPUHP_IOMMU_IOVA_DEAD);
>   		kmem_cache_destroy(iova_cache);
>   		kmem_cache_destroy(iova_magazine_cache);
> +		iova_cache = NULL;
> +		iova_magazine_cache = NULL;
>   	}
>   	mutex_unlock(&iova_cache_mutex);
>   }
Re: [PATCH] iommu/iova: Clear the slab cache pointers when destroying them
Posted by Davidlohr Bueso 2 days, 13 hours ago
On Mon, 17 Aug 2026, Robin Murphy wrote:

>On 16/08/2026 7:43 pm, Davidlohr Bueso wrote:
>>Both iova_cache_get() failure path and iova_cache_put() destroy the two
>>slab caches without clearing the pointers, leaving them dangling with
>>iova_cache_users at zero. The next iova_cache_get() then re-enters the
>>respective block, and if it fails early enough to reach 'out_err' before
>>re-creating both caches, it calls kmem_cache_destroy() a second time on
>>whichever cache is still stale:
>>
>>   BUG: KASAN: slab-use-after-free in iova_cache_get+0x216/0x280
>>   Read of size 1 at addr ffff888001b9fdc0 by task swapper/0/1
>>   CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.2.0-rc1 #2
>>   Call Trace:
>>    <TASK>
>>    dump_stack_lvl+0x53/0x70
>>    print_report+0xce/0x620
>>    kasan_report+0xce/0x100
>>    __kasan_check_byte+0x36/0x50
>>    kmem_cache_destroy+0x1b/0x1c0
>>    iova_cache_get+0x216/0x280
>>    ...
>>   Freed by task 1:
>>    kasan_save_stack+0x33/0x60
>>    kasan_save_track+0x14/0x30
>>    kasan_save_free_info+0x3b/0x60
>>    __kasan_slab_free+0x43/0x70
>>    kmem_cache_free+0xbe/0x3c0
>>    kobject_put+0x14d/0x280
>>    iova_cache_put+0x8e/0xd0
>>
>>Clear both pointers after destroying them, in both places.
>
>Out of curiosity, what architecture/kernel config have you found this
>with? I see the logic, but off the top of my head I'm somewhat
>struggling to imagine the scenario in which iova_cache_get() succeeds,
>the last user (so no iommu-dma) cleanly calls iova_cache_put() to be
>able to free the state, then another iova_cache_get() fails. Is
>everything else also falling apart in flames anyway at this point?

This was on x86-64, triggered through a dma fuzzer/stresser, but
could not reproduce this after leaving it running all week. What could
have happened, not sure, was that the program patched the code to
trigger the failure points, for which you can ignore this patch I guess.

Thanks,
Davidlohr