Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern KMEM_SIZE: append the size_t to the allocated buffe...



details:   https://anonhg.NetBSD.org/src/rev/1cb95fea825f
branches:  trunk
changeset: 1008005:1cb95fea825f
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Mar 08 00:31:19 2020 +0000

description:
KMEM_SIZE: append the size_t to the allocated buffer, rather than
prepending, so it doesn't screw up the alignment of the buffer.

Reported-by: syzbot+c024c50570cccac51532%syzkaller.appspotmail.com@localhost

diffstat:

 sys/kern/subr_kmem.c |  45 ++++++++++++++++++---------------------------
 1 files changed, 18 insertions(+), 27 deletions(-)

diffs (103 lines):

diff -r 6954e39c1975 -r 1cb95fea825f sys/kern/subr_kmem.c
--- a/sys/kern/subr_kmem.c      Sun Mar 08 00:26:06 2020 +0000
+++ b/sys/kern/subr_kmem.c      Sun Mar 08 00:31:19 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_kmem.c,v 1.78 2020/01/25 15:08:40 ad Exp $        */
+/*     $NetBSD: subr_kmem.c,v 1.79 2020/03/08 00:31:19 ad Exp $        */
 
 /*
  * Copyright (c) 2009-2020 The NetBSD Foundation, Inc.
@@ -62,23 +62,23 @@
 
 /*
  * KMEM_SIZE: detect alloc/free size mismatch bugs.
- *     Prefix each allocations with a fixed-sized, aligned header and record
- *     the exact user-requested allocation size in it. When freeing, compare
- *     it with kmem_free's "size" argument.
+ *     Append to each allocation a fixed-sized footer and record the exact
+ *     user-requested allocation size in it.  When freeing, compare it with
+ *     kmem_free's "size" argument.
  *
  * This option is enabled on DIAGNOSTIC.
  *
- *  |CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|
- *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+
- *  |/////|     |     |     |     |     |     |     |     |   |U|
- *  |/HSZ/|     |     |     |     |     |     |     |     |   |U|
- *  |/////|     |     |     |     |     |     |     |     |   |U|
- *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+
- *  |Size |    Buffer usable by the caller (requested size)   |Unused\
+ *  |CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK| |
+ *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-+
+ *  |     |     |     |     |     |     |     |     |/////|U|
+ *  |     |     |     |     |     |     |     |     |/HSZ/|U|
+ *  |     |     |     |     |     |     |     |     |/////|U|
+ *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+-+
+ *  | Buffer usable by the caller (requested size)  |Size |Unused
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.78 2020/01/25 15:08:40 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.79 2020/03/08 00:31:19 ad Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_kmem.h"
@@ -168,10 +168,7 @@
 #endif
 
 #if defined(KMEM_SIZE)
-struct kmem_header {
-       size_t          size;
-} __aligned(KMEM_ALIGN);
-#define        SIZE_SIZE       sizeof(struct kmem_header)
+#define        SIZE_SIZE       sizeof(size_t)
 static void kmem_size_set(void *, size_t);
 static void kmem_size_check(void *, size_t);
 #else
@@ -229,7 +226,6 @@
        if (__predict_true(p != NULL)) {
                FREECHECK_OUT(&kmem_freecheck, p);
                kmem_size_set(p, requested_size);
-               p += SIZE_SIZE;
                kasan_mark(p, origsize, size, KASAN_KMEM_REDZONE);
                return p;
        }
@@ -283,7 +279,6 @@
 
        kasan_mark(p, size, size, 0);
 
-       p = (uint8_t *)p - SIZE_SIZE;
        kmem_size_check(p, requested_size);
        FREECHECK_IN(&kmem_freecheck, p);
        LOCKDEBUG_MEM_CHECK(p, size);
@@ -485,25 +480,21 @@
 static void
 kmem_size_set(void *p, size_t sz)
 {
-       struct kmem_header *hd;
-       hd = (struct kmem_header *)p;
-       hd->size = sz;
+       memcpy((size_t *)((uintptr_t)p + sz), &sz, sizeof(size_t));
 }
 
 static void
 kmem_size_check(void *p, size_t sz)
 {
-       struct kmem_header *hd;
        size_t hsz;
 
-       hd = (struct kmem_header *)p;
-       hsz = hd->size;
+       memcpy(&hsz, (size_t *)((uintptr_t)p + sz), sizeof(size_t));
 
        if (hsz != sz) {
-               panic("kmem_free(%p, %zu) != allocated size %zu",
-                   (const uint8_t *)p + SIZE_SIZE, sz, hsz);
+               panic("kmem_free(%p, %zu) != allocated size %zu; overwrote?",
+                   p, sz, hsz);
        }
 
-       hd->size = -1;
+       memset((size_t *)((uintptr_t)p + sz), 0xff, sizeof(size_t));
 }
 #endif /* defined(KMEM_SIZE) */



Home | Main Index | Thread Index | Old Index