Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Jul 2026 22:36:24 +0000
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 990989c31b46 - main - uma: Make an effort to defer reuse of items when KASAN is enabled
Message-ID:  <6a63e8e8.188be.576e443f@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=990989c31b4637a23e64598a3d9929079bb9a8de

commit 990989c31b4637a23e64598a3d9929079bb9a8de
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-07-24 21:12:10 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-07-24 21:12:10 +0000

    uma: Make an effort to defer reuse of items when KASAN is enabled
    
    When KASAN is configured, make uma_zfree_arg() free items to the per-CPU
    free bucket, rather than to the alloc bucket.  This means that the item
    won't be recycled immediately the next time a thread goes to allocate an
    item from that zone on the same CPU.  In other words, the item will stay
    in a quarantine state longer, which helps make KASAN's use-after-free
    detection more reliable.
    
    Reviewed by:    rlibby
    MFC after:      1 month
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D58269
---
 sys/vm/uma_core.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 02b2df89f636..fb72fafe9abc 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -4447,8 +4447,11 @@ fail:
 	return (NULL);
 }
 
+/*
+ * Try to free an item to the per-CPU cache, promoting its quick reuse.
+ */
 static __always_inline bool
-cache_free_item(uma_zone_t zone, int uz_flags, void *item, void *udata)
+cache_free_reuse(uma_zone_t zone, int uz_flags, void *item, void *udata)
 {
 	uma_cache_t cache;
 	int itemdomain;
@@ -4504,8 +4507,14 @@ cache_free_item(uma_zone_t zone, int uz_flags, void *item, void *udata)
 	return (false);
 }
 
+/*
+ * Try to free an object to the per-CPU cache, deferring its reuse.  This is
+ * used by the SMR-protected allocator, which cannot reuse the item until
+ * smr_poll() guarantees that no threads are still accessing it, and by
+ * sanitizers, which wish to defer reuse to make UAF detection more effective.
+ */
 static __always_inline bool
-cache_free_smr(uma_zone_t zone, void *item, void *udata)
+cache_free_defer(uma_zone_t zone, void *item, void *udata)
 {
 	uma_cache_t cache;
 	int itemdomain;
@@ -4524,7 +4533,6 @@ cache_free_smr(uma_zone_t zone, void *item, void *udata)
 		uma_cache_bucket_t bucket;
 
 		cache = &zone->uz_cpu[curcpu];
-		/* SMR Zones must free to the free bucket. */
 		bucket = &cache->uc_freebucket;
 #ifdef NUMA
 		if ((uz_flags & UMA_ZONE_FIRSTTOUCH) != 0 &&
@@ -4559,7 +4567,7 @@ uma_zfree_smr(uma_zone_t zone, void *item)
 		return;
 #endif
 
-	if (cache_free_smr(zone, item, NULL))
+	if (cache_free_defer(zone, item, NULL))
 		return;
 
 	/*
@@ -4607,16 +4615,22 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
 	 * a little longer for the limits to be reset.
 	 */
 	if (__predict_false(uz_flags & UMA_ZFLAG_LIMIT) &&
-	    atomic_load_32(&zone->uz_sleepers) > 0)
-		goto zfree_item;
-
-	if (cache_free_item(zone, uz_flags, item, udata))
+	    atomic_load_32(&zone->uz_sleepers) > 0) {
+		/* We will free directly to the zone. */
+	}
+#ifdef KASAN
+	else if ((uz_flags & UMA_ZONE_NOKASAN) == 0) {
+		if (cache_free_defer(zone, item, udata))
+			return;
+	}
+#endif
+	else if (cache_free_reuse(zone, uz_flags, item, udata)) {
 		return;
+	}
 
 	/*
 	 * If nothing else caught this, we'll just do an internal free.
 	 */
-zfree_item:
 	zone_free_item(zone, item, udata, SKIP_DTOR);
 }
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a63e8e8.188be.576e443f>