⬢ DragonFlyBSD Kernel Audit
DF-2820 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/kern_kmalloc.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/kern/kern_kmalloc.c	2026-10-26 00:25:42.813042622 +0000
@@ -647,6 +647,19 @@
 	atomic_clear_64(ptr, mask);
 }
 
+static __inline int
+bmap_test(struct kmalloc_slab *slab, void *obj)
+{
+	uint64_t *ptr;
+	uint64_t mask;
+	size_t i = (((uintptr_t)obj & KMALLOC_SLAB_MASK) - slab->offset) /
+		   slab->objsize;
+
+	ptr = &slab->bmap[i >> 6];
+	mask = (uint64_t)1U << (i & 63);
+	return ((*ptr & mask) != 0);
+}
+
 #endif
 
 /*
@@ -961,6 +974,21 @@
 			slab->aindex, slab->findex, slab->ncount);
 	}
 #ifdef KMALLOC_CHECK_DOUBLE_FREE
+	/*
+	 * Unconditional (production too) containment: refuse a double
+	 * free and keep the free ring sane instead of silently storing
+	 * the same pointer twice.
+	 */
+	if (bmap_test(slab, obj) == 0) {
+		static volatile int df_report = 10;
+
+		if (atomic_fetchadd_int(&df_report, -1) > 0) {
+			kprintf("_kfree_obj: double free of %p detected, "
+				"refusing\n", obj);
+		}
+		crit_exit();
+		return;
+	}
 	bmap_clr(slab, obj);
 #endif
 	KKASSERT(slab->fobjs[i] == NULL);