DF-2820 / fix.diff
--- 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); |