Date: Fri, 31 Jul 2026 13:29: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: 459aa032e872 - main - malloc: Refactor redzone and sanitizer handling Message-ID: <6a6ca334.1990d.4d2bf785@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=459aa032e87275ebe10847592ea2ddea0c3ed693 commit 459aa032e87275ebe10847592ea2ddea0c3ed693 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-07-31 12:55:59 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-07-31 12:55:59 +0000 malloc: Refactor redzone and sanitizer handling malloc_large() duplicates redzone and KASAN handling that is also present in malloc() and malloc_domainset(). Refactor the implementations to reduce this a bit. Also normalize KMSAN map handling: make malloc() and malloc_domainset() consistent, and do not update the KMSAN shadow map, as we can rely on UMA and kmem_malloc() to handle that. Reviewed by: rlibby MFC after: 3 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58272 --- sys/kern/kern_malloc.c | 136 +++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 84 deletions(-) diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index fcbfbe64f854..0be0a417e19c 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -108,14 +108,6 @@ dtrace_malloc_probe_func_t __read_mostly dtrace_malloc_probe; #define MALLOC_DEBUG 1 #endif -#if defined(KASAN) || defined(DEBUG_REDZONE) -#define DEBUG_REDZONE_ARG_DEF , unsigned long osize -#define DEBUG_REDZONE_ARG , osize -#else -#define DEBUG_REDZONE_ARG_DEF -#define DEBUG_REDZONE_ARG -#endif - typedef enum { SLAB_COOKIE_SLAB_PTR = 0x0, SLAB_COOKIE_MALLOC_LARGE = 0x1, @@ -541,7 +533,7 @@ contigfree(void *addr, unsigned long size __unused, struct malloc_type *type) #ifdef MALLOC_DEBUG static int -malloc_dbg(caddr_t *vap, size_t *sizep, struct malloc_type *mtp, +malloc_dbg(void **vap, size_t *sizep, struct malloc_type *mtp, int flags) { KASSERT(mtp->ks_version == M_VERSION, ("malloc: bad malloc type version")); @@ -611,12 +603,13 @@ malloc_large_size(uma_slab_t slab) } static caddr_t __noinline -malloc_large(size_t size, struct malloc_type *mtp, struct domainset *policy, - int flags DEBUG_REDZONE_ARG_DEF) +malloc_large(size_t *sizep, struct malloc_type *mtp, struct domainset *policy, + int flags) { void *va; + size_t size; - size = roundup(size, PAGE_SIZE); + size = roundup(*sizep, PAGE_SIZE); va = kmem_malloc_domainset(policy, size, flags); if (va != NULL) { /* Use low bits unused for slab pointers. */ @@ -624,15 +617,7 @@ malloc_large(size_t size, struct malloc_type *mtp, struct domainset *policy, uma_total_inc(size); } malloc_type_allocated(mtp, va == NULL ? 0 : size); - if (__predict_false(va == NULL)) { - KASSERT((flags & M_WAITOK) == 0, - ("malloc(M_WAITOK) returned NULL")); - } else { -#ifdef DEBUG_REDZONE - va = redzone_setup(va, osize); -#endif - kasan_mark(va, osize, size, KASAN_MALLOC_REDZONE); - } + *sizep = size; return (va); } @@ -657,13 +642,14 @@ free_large(void *addr, size_t size) void * (malloc)(size_t size, struct malloc_type *mtp, int flags) { - int indx; - caddr_t va; uma_zone_t zone; + void *va; + int indx; #if defined(DEBUG_REDZONE) || defined(KASAN) unsigned long osize = size; #endif + /* We don't want to handle this rare case in a hot path. */ MPASS((flags & M_EXEC) == 0); #ifdef MALLOC_DEBUG @@ -672,36 +658,34 @@ void * return (va); #endif - if (__predict_false(size > kmem_zmax)) - return (malloc_large(size, mtp, DOMAINSET_RR(), flags - DEBUG_REDZONE_ARG)); - - if (size & KMEM_ZMASK) - size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; - indx = kmemsize[size >> KMEM_ZSHIFT]; - zone = kmemzones[indx].kz_zone[mtp_get_subzone(mtp)]; - va = uma_zalloc_arg(zone, zone, flags); - if (va != NULL) { - size = zone->uz_size; - if ((flags & M_ZERO) == 0) { - kmsan_mark(va, size, KMSAN_STATE_UNINIT); - kmsan_orig(va, size, KMSAN_TYPE_MALLOC, KMSAN_RET_ADDR); - } - } - malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); - if (__predict_false(va == NULL)) { - KASSERT((flags & M_WAITOK) == 0, - ("malloc(M_WAITOK) returned NULL")); + if (__predict_false(size > kmem_zmax)) { + va = malloc_large(&size, mtp, DOMAINSET_RR(), flags); + } else { + if (size & KMEM_ZMASK) + size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; + indx = kmemsize[size >> KMEM_ZSHIFT]; + zone = kmemzones[indx].kz_zone[mtp_get_subzone(mtp)]; + va = uma_zalloc_arg(zone, zone, flags); + if (va != NULL) + size = zone->uz_size; + malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); } + KASSERT(va != NULL || (flags & M_WAITOK) == 0, + ("malloc(M_WAITOK) returned NULL")); + #ifdef DEBUG_REDZONE if (va != NULL) va = redzone_setup(va, osize); #endif #ifdef KASAN if (va != NULL) - kasan_mark((void *)va, osize, size, KASAN_MALLOC_REDZONE); + kasan_mark(va, osize, size, KASAN_MALLOC_REDZONE); +#endif +#ifdef KMSAN + if (va != NULL && (flags & M_ZERO) == 0) + kmsan_orig(va, size, KMSAN_TYPE_MALLOC, KMSAN_RET_ADDR); #endif - return ((void *) va); + return (va); } static void * @@ -732,50 +716,49 @@ malloc_domainset(size_t size, struct malloc_type *mtp, struct domainset *ds, int flags) { struct vm_domainset_iter di; - caddr_t va; + void *va; int domain; - int indx; #if defined(KASAN) || defined(DEBUG_REDZONE) unsigned long osize = size; #endif - MPASS((flags & M_EXEC) == 0); - #ifdef MALLOC_DEBUG va = NULL; if (malloc_dbg(&va, &size, mtp, flags) != 0) return (va); #endif - if (__predict_false(size > kmem_zmax)) - return (malloc_large(size, mtp, DOMAINSET_RR(), flags - DEBUG_REDZONE_ARG)); - - indx = -1; - va = NULL; - if (vm_domainset_iter_policy_init(&di, ds, &domain, &flags) == 0) - do { - va = malloc_domain(&size, &indx, mtp, domain, flags); - } while (va == NULL && vm_domainset_iter_policy(&di, &domain) == 0); - malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); - - if (__predict_false(va == NULL)) { - KASSERT((flags & M_WAITOK) == 0, - ("malloc(M_WAITOK) returned NULL")); + if (__predict_false(size > kmem_zmax || (flags & M_EXEC) != 0)) { + va = malloc_large(&size, mtp, DOMAINSET_RR(), flags); + } else { + int indx; + + indx = -1; + va = NULL; + if (vm_domainset_iter_policy_init(&di, ds, &domain, + &flags) == 0) { + do { + va = malloc_domain(&size, &indx, mtp, domain, + flags); + } while (va == NULL && + vm_domainset_iter_policy(&di, &domain) == 0); + } + malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); } + KASSERT(va != NULL || (flags & M_WAITOK) == 0, + ("malloc(M_WAITOK) returned NULL")); + #ifdef DEBUG_REDZONE if (va != NULL) va = redzone_setup(va, osize); #endif #ifdef KASAN if (va != NULL) - kasan_mark((void *)va, osize, size, KASAN_MALLOC_REDZONE); + kasan_mark(va, osize, size, KASAN_MALLOC_REDZONE); #endif #ifdef KMSAN - if ((flags & M_ZERO) == 0) { - kmsan_mark(va, size, KMSAN_STATE_UNINIT); + if (va != NULL && (flags & M_ZERO) == 0) kmsan_orig(va, size, KMSAN_TYPE_MALLOC, KMSAN_RET_ADDR); - } #endif return (va); } @@ -794,22 +777,7 @@ void * malloc_domainset_exec(size_t size, struct malloc_type *mtp, struct domainset *ds, int flags) { -#if defined(DEBUG_REDZONE) || defined(KASAN) - unsigned long osize = size; -#endif -#ifdef MALLOC_DEBUG - caddr_t va; -#endif - - flags |= M_EXEC; - -#ifdef MALLOC_DEBUG - va = NULL; - if (malloc_dbg(&va, &size, mtp, flags) != 0) - return (va); -#endif - - return (malloc_large(size, mtp, ds, flags DEBUG_REDZONE_ARG)); + return (malloc_domainset(size, mtp, ds, flags | M_EXEC)); } void *home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a6ca334.1990d.4d2bf785>
