Source-Changes-HG archive

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

[src/trunk]: src/sys/kern Retire KMEM_REDZONE and KMEM_POISON.



details:   https://anonhg.NetBSD.org/src/rev/7cbdf3fc4114
branches:  trunk
changeset: 365538:7cbdf3fc4114
user:      maxv <maxv%NetBSD.org@localhost>
date:      Mon Aug 20 11:35:28 2018 +0000

description:
Retire KMEM_REDZONE and KMEM_POISON.

KMEM_REDZONE is not very efficient and cannot detect read overflows. KASAN
can, and will be used instead.

KMEM_POISON is enabled along with KMEM_GUARD, but it is redundant, since
the latter can detect read UAFs contrary to the former. In fact maybe
KMEM_GUARD should be retired too, because there are many cases where it
doesn't apply.

Simplifies the code.

diffstat:

 sys/kern/files.kern  |    4 +-
 sys/kern/subr_kmem.c |  197 +++-----------------------------------------------
 2 files changed, 15 insertions(+), 186 deletions(-)

diffs (truncated from 319 to 300 lines):

diff -r 0f5a90c6ad31 -r 7cbdf3fc4114 sys/kern/files.kern
--- a/sys/kern/files.kern       Mon Aug 20 10:57:52 2018 +0000
+++ b/sys/kern/files.kern       Mon Aug 20 11:35:28 2018 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.kern,v 1.21 2018/08/03 04:35:20 kamil Exp $
+#      $NetBSD: files.kern,v 1.22 2018/08/20 11:35:28 maxv Exp $
 
 #
 # kernel sources
@@ -116,8 +116,6 @@
 file   kern/subr_ipi.c                 kern
 file   kern/subr_kcpuset.c             kern
 defflag        opt_kmem.h                      KMEM_GUARD
-                                       KMEM_POISON
-                                       KMEM_REDZONE
                                        KMEM_SIZE
 defparam opt_kmem.h                    KMEM_GUARD_DEPTH
 file   kern/subr_kmem.c                kern
diff -r 0f5a90c6ad31 -r 7cbdf3fc4114 sys/kern/subr_kmem.c
--- a/sys/kern/subr_kmem.c      Mon Aug 20 10:57:52 2018 +0000
+++ b/sys/kern/subr_kmem.c      Mon Aug 20 11:35:28 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_kmem.c,v 1.66 2018/01/09 01:53:55 christos Exp $  */
+/*     $NetBSD: subr_kmem.c,v 1.67 2018/08/20 11:35:28 maxv Exp $      */
 
 /*-
  * Copyright (c) 2009-2015 The NetBSD Foundation, Inc.
@@ -66,26 +66,18 @@
  *     the exact user-requested allocation size in it. When freeing, compare
  *     it with kmem_free's "size" argument.
  *
- * KMEM_REDZONE: detect overrun bugs.
- *     Add a 2-byte pattern (allocate one more memory chunk if needed) at the
- *     end of each allocated buffer. Check this pattern on kmem_free.
- *
- * These options are enabled on DIAGNOSTIC.
+ * This option enabled on DIAGNOSTIC.
  *
- *  |CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|
- *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+--+--+
- *  |/////|     |     |     |     |     |     |     |     |   |*|**|UU|
- *  |/HSZ/|     |     |     |     |     |     |     |     |   |*|**|UU|
- *  |/////|     |     |     |     |     |     |     |     |   |*|**|UU|
- *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+--+--+
- *  |Size |    Buffer usable by the caller (requested size)   |RedZ|Unused\
+ *  |CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|CHUNK|
+ *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+
+ *  |/////|     |     |     |     |     |     |     |     |   |U|
+ *  |/HSZ/|     |     |     |     |     |     |     |     |   |U|
+ *  |/////|     |     |     |     |     |     |     |     |   |U|
+ *  +-----+-----+-----+-----+-----+-----+-----+-----+-----+---+-+
+ *  |Size |    Buffer usable by the caller (requested size)   |Unused\
  */
 
 /*
- * KMEM_POISON: detect modify-after-free bugs.
- *     Fill freed (in the sense of kmem_free) memory with a garbage pattern.
- *     Check the pattern on allocation.
- *
  * KMEM_GUARD
  *     A kernel with "option DEBUG" has "kmem_guard" debugging feature compiled
  *     in. See the comment below for what kind of bugs it tries to detect. Even
@@ -100,7 +92,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.66 2018/01/09 01:53:55 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.67 2018/08/20 11:35:28 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_kmem.h"
@@ -181,34 +173,13 @@
 
 #if defined(DIAGNOSTIC) && defined(_HARDKERNEL)
 #define        KMEM_SIZE
-#define        KMEM_REDZONE
-#endif /* defined(DIAGNOSTIC) */
+#endif
 
 #if defined(DEBUG) && defined(_HARDKERNEL)
 #define        KMEM_SIZE
-#define        KMEM_POISON
 #define        KMEM_GUARD
 static void *kmem_freecheck;
-#endif /* defined(DEBUG) */
-
-#if defined(KMEM_POISON)
-static int kmem_poison_ctor(void *, void *, int);
-static void kmem_poison_fill(void *, size_t);
-static void kmem_poison_check(void *, size_t);
-#else /* defined(KMEM_POISON) */
-#define        kmem_poison_fill(p, sz)         /* nothing */
-#define        kmem_poison_check(p, sz)        /* nothing */
-#endif /* defined(KMEM_POISON) */
-
-#if defined(KMEM_REDZONE)
-#define        REDZONE_SIZE    2
-static void kmem_redzone_fill(void *, size_t);
-static void kmem_redzone_check(void *, size_t);
-#else /* defined(KMEM_REDZONE) */
-#define        REDZONE_SIZE    0
-#define        kmem_redzone_fill(p, sz)                /* nothing */
-#define        kmem_redzone_check(p, sz)       /* nothing */
-#endif /* defined(KMEM_REDZONE) */
+#endif
 
 #if defined(KMEM_SIZE)
 struct kmem_header {
@@ -233,11 +204,9 @@
        u_int           kg_rotor;
        vmem_t *        kg_vmem;
 };
-
-static bool    kmem_guard_init(struct kmem_guard *, u_int, vmem_t *);
+static bool kmem_guard_init(struct kmem_guard *, u_int, vmem_t *);
 static void *kmem_guard_alloc(struct kmem_guard *, size_t, bool);
 static void kmem_guard_free(struct kmem_guard *, size_t, void *);
-
 int kmem_guard_depth = KMEM_GUARD_DEPTH;
 static bool kmem_guard_enabled;
 static struct kmem_guard kmem_guard;
@@ -269,17 +238,10 @@
                    (kmflags & KM_SLEEP) != 0);
        }
 #endif
+
        size = kmem_roundup_size(requested_size);
        allocsz = size + SIZE_SIZE;
 
-#ifdef KMEM_REDZONE
-       if (size - requested_size < REDZONE_SIZE) {
-               /* If there isn't enough space in the padding, allocate
-                * one more memory chunk for the red zone. */
-               allocsz += kmem_roundup_size(REDZONE_SIZE);
-       }
-#endif
-
        if ((index = ((allocsz -1) >> KMEM_SHIFT))
            < kmem_cache_maxidx) {
                pc = kmem_cache[index];
@@ -301,10 +263,8 @@
        p = pool_cache_get(pc, kmflags);
 
        if (__predict_true(p != NULL)) {
-               kmem_poison_check(p, allocsz);
                FREECHECK_OUT(&kmem_freecheck, p);
                kmem_size_set(p, requested_size);
-               kmem_redzone_fill(p, requested_size + SIZE_SIZE);
 
                return p + SIZE_SIZE;
        }
@@ -351,12 +311,6 @@
        size = kmem_roundup_size(requested_size);
        allocsz = size + SIZE_SIZE;
 
-#ifdef KMEM_REDZONE
-       if (size - requested_size < REDZONE_SIZE) {
-               allocsz += kmem_roundup_size(REDZONE_SIZE);
-       }
-#endif
-
        if ((index = ((allocsz -1) >> KMEM_SHIFT))
            < kmem_cache_maxidx) {
                pc = kmem_cache[index];
@@ -372,10 +326,8 @@
 
        p = (uint8_t *)p - SIZE_SIZE;
        kmem_size_check(p, requested_size);
-       kmem_redzone_check(p, requested_size + SIZE_SIZE);
        FREECHECK_IN(&kmem_freecheck, p);
        LOCKDEBUG_MEM_CHECK(p, size);
-       kmem_poison_fill(p, allocsz);
 
        pool_cache_put(pc, p);
 }
@@ -469,14 +421,8 @@
                }
 
                pa = &pool_allocator_kmem;
-#if defined(KMEM_POISON)
-               pc = pool_cache_init(cache_size, align, 0, flags,
-                   name, pa, ipl, kmem_poison_ctor,
-                   NULL, (void *)cache_size);
-#else /* defined(KMEM_POISON) */
                pc = pool_cache_init(cache_size, align, 0, flags,
                    name, pa, ipl, NULL, NULL, NULL);
-#endif /* defined(KMEM_POISON) */
 
                while (size <= cache_size) {
                        alloc_table[(size - 1) >> shift] = pc;
@@ -572,66 +518,6 @@
 
 /* ------------------ DEBUG / DIAGNOSTIC ------------------ */
 
-#if defined(KMEM_POISON) || defined(KMEM_REDZONE)
-#if defined(_LP64)
-#define PRIME 0x9e37fffffffc0000UL
-#else /* defined(_LP64) */
-#define PRIME 0x9e3779b1
-#endif /* defined(_LP64) */
-
-static inline uint8_t
-kmem_pattern_generate(const void *p)
-{
-       return (uint8_t)(((uintptr_t)p) * PRIME
-          >> ((sizeof(uintptr_t) - sizeof(uint8_t))) * CHAR_BIT);
-}
-#endif /* defined(KMEM_POISON) || defined(KMEM_REDZONE) */
-
-#if defined(KMEM_POISON)
-static int
-kmem_poison_ctor(void *arg, void *obj, int flag)
-{
-       size_t sz = (size_t)arg;
-
-       kmem_poison_fill(obj, sz);
-
-       return 0;
-}
-
-static void
-kmem_poison_fill(void *p, size_t sz)
-{
-       uint8_t *cp;
-       const uint8_t *ep;
-
-       cp = p;
-       ep = cp + sz;
-       while (cp < ep) {
-               *cp = kmem_pattern_generate(cp);
-               cp++;
-       }
-}
-
-static void
-kmem_poison_check(void *p, size_t sz)
-{
-       uint8_t *cp;
-       const uint8_t *ep;
-
-       cp = p;
-       ep = cp + sz;
-       while (cp < ep) {
-               const uint8_t expected = kmem_pattern_generate(cp);
-
-               if (*cp != expected) {
-                       panic("%s: %p: 0x%02x != 0x%02x\n",
-                          __func__, cp, *cp, expected);
-               }
-               cp++;
-       }
-}
-#endif /* defined(KMEM_POISON) */
-
 #if defined(KMEM_SIZE)
 static void
 kmem_size_set(void *p, size_t sz)
@@ -657,61 +543,6 @@
 }
 #endif /* defined(KMEM_SIZE) */
 
-#if defined(KMEM_REDZONE)
-#define STATIC_BYTE    0xFE
-CTASSERT(REDZONE_SIZE > 1);
-static void
-kmem_redzone_fill(void *p, size_t sz)
-{
-       uint8_t *cp, pat;
-       const uint8_t *ep;
-
-       cp = (uint8_t *)p + sz;
-       ep = cp + REDZONE_SIZE;
-
-       /*
-        * We really don't want the first byte of the red zone to be '\0';
-        * an off-by-one in a string may not be properly detected.
-        */
-       pat = kmem_pattern_generate(cp);
-       *cp = (pat == '\0') ? STATIC_BYTE: pat;
-       cp++;
-
-       while (cp < ep) {
-               *cp = kmem_pattern_generate(cp);
-               cp++;
-       }
-}
-
-static void
-kmem_redzone_check(void *p, size_t sz)
-{
-       uint8_t *cp, pat, expected;
-       const uint8_t *ep;
-
-       cp = (uint8_t *)p + sz;
-       ep = cp + REDZONE_SIZE;
-
-       pat = kmem_pattern_generate(cp);
-       expected = (pat == '\0') ? STATIC_BYTE: pat;
-       if (expected != *cp) {
-               panic("%s: %p: 0x%02x != 0x%02x\n",



Home | Main Index | Thread Index | Old Index