Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Sep 2024 10:38:10 GMT
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 87d3af98590b - stable/14 - kern_malloc: fold free and zfree together into one __always_inline func
Message-ID:  <202409281038.48SAcA1Z097606@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=87d3af98590bbf09509822ec94c596d69f53411e

commit 87d3af98590bbf09509822ec94c596d69f53411e
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-07-24 15:56:32 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2024-09-28 10:35:12 +0000

    kern_malloc: fold free and zfree together into one __always_inline func
    
    free() and zfree() are essentially the same copy and pasted code with
    the extra explicit_bzero() (and formerly kasan) calls.  Add a bool to add
    the extra functionality and make both functions a wrapper around the common
    code and let the compiler do the optimization based on the bool input
    when inlining.
    
    No functional changes intended.
    
    Suggested by:   kib (in D45812)
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    kib, markj
    Differential Revision: https://reviews.freebsd.org/D46101
    
    And the fix from Olivier Certner (olce):
    
    kern_malloc: Restore working KASAN runtime after free() and zfree() folding
    
    In the zfree() case, the explicit_bzero() calls zero all the allocation,
    including the redzone which malloc() has marked as invalid.  So calling
    kasan_mark() before those is in fact necessary.
    
    This fixes a crash at boot when 'ldconfig' is run and tries to get
    random bytes through getrandom() (relevant part of the stack is
    read_random_uio() -> zfree() -> explicit_bzero()) for kernels with KASAN
    compiled in.
    
    Approved by:    markj (mentor)
    Fixes:          4fab5f005482 ("kern_malloc: fold free and zfree together into one __always_inline func")
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 4fab5f005482aa88bc0f7d7a0a5e81b436869112)
    (cherry picked from commit 28391f188ca18b6251ba46040adf81946b0ccb03)
---
 sys/kern/kern_malloc.c | 94 +++++++++++++++++---------------------------------
 1 file changed, 31 insertions(+), 63 deletions(-)

diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 403f5fe11455..3fef90b5fa82 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -922,15 +922,8 @@ free_dbg(void **addrp, struct malloc_type *mtp)
 }
 #endif
 
-/*
- *	free:
- *
- *	Free a block of memory allocated by malloc.
- *
- *	This routine may not block.
- */
-void
-free(void *addr, struct malloc_type *mtp)
+static __always_inline void
+_free(void *addr, struct malloc_type *mtp, bool dozero)
 {
 	uma_zone_t zone;
 	uma_slab_t slab;
@@ -946,8 +939,8 @@ free(void *addr, struct malloc_type *mtp)
 
 	vtozoneslab((vm_offset_t)addr & (~UMA_SLAB_MASK), &zone, &slab);
 	if (slab == NULL)
-		panic("free: address %p(%p) has not been allocated",
-		    addr, (void *)((u_long)addr & (~UMA_SLAB_MASK)));
+		panic("%s(%d): address %p(%p) has not been allocated", __func__,
+		    dozero, addr, (void *)((uintptr_t)addr & (~UMA_SLAB_MASK)));
 
 	switch (GET_SLAB_COOKIE(slab)) {
 	case __predict_true(SLAB_COOKIE_SLAB_PTR):
@@ -955,79 +948,54 @@ free(void *addr, struct malloc_type *mtp)
 #if defined(INVARIANTS) && !defined(KASAN)
 		free_save_type(addr, mtp, size);
 #endif
+		if (dozero) {
+			kasan_mark(addr, size, size, 0);
+			explicit_bzero(addr, size);
+		}
 		uma_zfree_arg(zone, addr, slab);
 		break;
 	case SLAB_COOKIE_MALLOC_LARGE:
 		size = malloc_large_size(slab);
+		if (dozero) {
+			kasan_mark(addr, size, size, 0);
+			explicit_bzero(addr, size);
+		}
 		free_large(addr, size);
 		break;
 	case SLAB_COOKIE_CONTIG_MALLOC:
-		size = contigmalloc_size(slab);
+		size = round_page(contigmalloc_size(slab));
+		if (dozero)
+			explicit_bzero(addr, size);
 		kmem_free(addr, size);
-		size = round_page(size);
 		break;
 	default:
-		panic("%s: addr %p slab %p with unknown cookie %d", __func__,
-		    addr, slab, GET_SLAB_COOKIE(slab));
+		panic("%s(%d): addr %p slab %p with unknown cookie %d",
+		    __func__, dozero, addr, slab, GET_SLAB_COOKIE(slab));
 		/* NOTREACHED */
 	}
 	malloc_type_freed(mtp, size);
 }
 
 /*
- *	zfree:
- *
- *	Zero then free a block of memory allocated by malloc.
- *
+ * free:
+ *	Free a block of memory allocated by malloc/contigmalloc.
  *	This routine may not block.
  */
 void
-zfree(void *addr, struct malloc_type *mtp)
+free(void *addr, struct malloc_type *mtp)
 {
-	uma_zone_t zone;
-	uma_slab_t slab;
-	u_long size;
-
-#ifdef MALLOC_DEBUG
-	if (free_dbg(&addr, mtp) != 0)
-		return;
-#endif
-	/* free(NULL, ...) does nothing */
-	if (addr == NULL)
-		return;
-
-	vtozoneslab((vm_offset_t)addr & (~UMA_SLAB_MASK), &zone, &slab);
-	if (slab == NULL)
-		panic("free: address %p(%p) has not been allocated",
-		    addr, (void *)((u_long)addr & (~UMA_SLAB_MASK)));
+	_free(addr, mtp, false);
+}
 
-	switch (GET_SLAB_COOKIE(slab)) {
-	case __predict_true(SLAB_COOKIE_SLAB_PTR):
-		size = zone->uz_size;
-#if defined(INVARIANTS) && !defined(KASAN)
-		free_save_type(addr, mtp, size);
-#endif
-		kasan_mark(addr, size, size, 0);
-		explicit_bzero(addr, size);
-		uma_zfree_arg(zone, addr, slab);
-		break;
-	case SLAB_COOKIE_MALLOC_LARGE:
-		size = malloc_large_size(slab);
-		kasan_mark(addr, size, size, 0);
-		explicit_bzero(addr, size);
-		free_large(addr, size);
-		break;
-	case SLAB_COOKIE_CONTIG_MALLOC:
-		size = round_page(contigmalloc_size(slab));
-		explicit_bzero(addr, size);
-		kmem_free(addr, size);
-		break;
-	default:
-		panic("%s: addr %p slab %p with unknown cookie %d", __func__,
-		    addr, slab, GET_SLAB_COOKIE(slab));
-		/* NOTREACHED */
-	}
-	malloc_type_freed(mtp, size);
+/*
+ * zfree:
+ *	Zero then free a block of memory allocated by malloc/contigmalloc.
+ *	This routine may not block.
+ */
+void
+zfree(void *addr, struct malloc_type *mtp)
+{
+	_free(addr, mtp, true);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202409281038.48SAcA1Z097606>