here's diff x/y. most of the big pieces in place, so now I want to
rearrange the deckchairs just the way I like. A bunch of unreleated
changes collected here instead of mailing out a pile of overlapping
diffs you could never apply independently. This settles things down in
prep for some more interesting changes.

- move poison prototypes from systm.h to malloc.h
- add poison_value() which returns the poison value appropriate for
this pointer
- use poison_value throughout malloc and pool
- increase poison size to 64. the old malloc code was effectively 128
(32 * sizeof(int)) and pool was whatever the item size is. i think 32
is a little on the small side, 64 should be enough to catch most errors.
- move kmem_freelist definition back into malloc, a forward decl
suffices.
- the magic field can remain in pool item headers unconditionally, so
remove the ifdef guard. i don't like size changing structs, even local
ones.
- make some POOL_DEBUG less conditional. this allows the pool_debug
sysctl to actually do something on release kernels. still won't have
much performance impact because all the poisoning is runtime guarded
as well.
- maybe some other stuff i forgot to mention. read the diff.


Index: sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.103
diff -u -p -r1.103 malloc.h
--- sys/malloc.h        26 Mar 2013 16:36:01 -0000      1.103
+++ sys/malloc.h        31 Mar 2013 02:02:54 -0000
@@ -341,20 +341,7 @@ struct kmemusage {
 #define        ku_freecnt ku_un.freecnt
 #define        ku_pagecnt ku_un.pagecnt
 
-/*
- * Normally the freelist structure is used only to hold the list pointer
- * for free objects.  However, when running with diagnostics, the first
- * 8 bytes of the structure is unused except for diagnostic information,
- * and the free list pointer is at offset 8 in the structure.  Since the
- * first 8 bytes is the portion of the structure most often modified, this
- * helps to detect memory reuse problems and avoid free list corruption.
- */
-struct kmem_freelist {
-       int32_t kf_spare0;
-       int16_t kf_type;
-       int16_t kf_spare1;
-       SIMPLEQ_ENTRY(kmem_freelist) kf_flist;
-};
+struct kmem_freelist;
 
 /*
  * Set of buckets for each size of memory block that is retained
@@ -410,6 +397,10 @@ extern int sysctl_malloc(int *, u_int, v
 
 size_t malloc_roundup(size_t);
 void   malloc_printit(int (*)(const char *, ...));
+
+void   poison_mem(void *, size_t);
+int    poison_check(void *, size_t, size_t *, int *);
+int32_t poison_value(void *);
 
 #ifdef MALLOC_DEBUG
 int    debug_malloc(unsigned long, int, int, void **);
Index: sys/systm.h
===================================================================
RCS file: /cvs/src/sys/sys/systm.h,v
retrieving revision 1.96
diff -u -p -r1.96 systm.h
--- sys/systm.h 28 Mar 2013 16:41:39 -0000      1.96
+++ sys/systm.h 31 Mar 2013 02:01:21 -0000
@@ -187,9 +187,6 @@ extern      int splassert_ctl;
 
 void   assertwaitok(void);
 
-void   poison_mem(void *, size_t);
-int    poison_check(void *, size_t, size_t *, int *);
-
 void   tablefull(const char *);
 
 int    kcopy(const void *, void *, size_t)
Index: kern/kern_malloc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.98
diff -u -p -r1.98 kern_malloc.c
--- kern/kern_malloc.c  28 Mar 2013 16:41:39 -0000      1.98
+++ kern/kern_malloc.c  31 Mar 2013 02:03:48 -0000
@@ -120,6 +120,21 @@ char *memall = NULL;
 struct rwlock sysctl_kmemlock = RWLOCK_INITIALIZER("sysctlklk");
 #endif
 
+/*
+ * Normally the freelist structure is used only to hold the list pointer
+ * for free objects.  However, when running with diagnostics, the first
+ * 8 bytes of the structure is unused except for diagnostic information,
+ * and the free list pointer is at offset 8 in the structure.  Since the
+ * first 8 bytes is the portion of the structure most often modified, this
+ * helps to detect memory reuse problems and avoid free list corruption.
+ */
+struct kmem_freelist {
+       int32_t kf_spare0;
+       int16_t kf_type;
+       int16_t kf_spare1;
+       SIMPLEQ_ENTRY(kmem_freelist) kf_flist;
+};
+
 #ifdef DIAGNOSTIC
 /*
  * This structure provides a set of masks to catch unaligned frees.
@@ -131,16 +146,6 @@ const long addrmask[] = { 0,
        0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
 };
 
-/*
- * The FREELIST_MARKER is used as known text to copy into free objects so
- * that modifications after frees can be detected.
- */
-#ifdef DEADBEEF0
-#define FREELIST_MARKER        ((unsigned) DEADBEEF0)
-#else
-#define FREELIST_MARKER        ((unsigned) 0xdeadbeef)
-#endif
-
 #endif /* DIAGNOSTIC */
 
 #ifndef SMALL_KERNEL
@@ -413,7 +418,7 @@ free(void *addr, int type)
         * Check for multiple frees. Use a quick check to see if
         * it looks free before laboriously searching the freelist.
         */
-       if (freep->kf_spare0 == FREELIST_MARKER) {
+       if (freep->kf_spare0 == poison_value(freep)) {
                struct kmem_freelist *fp;
                SIMPLEQ_FOREACH(fp, &kbp->kb_freelist, kf_flist) {
                        if (addr != fp)
@@ -429,7 +434,7 @@ free(void *addr, int type)
         * when the object is reallocated.
         */
        poison_mem(addr, size);
-       freep->kf_spare0 = FREELIST_MARKER;
+       freep->kf_spare0 = poison_value(freep);
 
        freep->kf_type = type;
 #endif /* DIAGNOSTIC */
Index: kern/subr_poison.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_poison.c,v
retrieving revision 1.1
diff -u -p -r1.1 subr_poison.c
--- kern/subr_poison.c  28 Mar 2013 16:41:39 -0000      1.1
+++ kern/subr_poison.c  31 Mar 2013 02:06:45 -0000
@@ -16,7 +16,7 @@
  */
 
 #include <sys/types.h>
-#include <sys/systm.h>
+#include <sys/malloc.h>
 
 /*
  * The POISON is used as known text to copy into free objects so
@@ -27,33 +27,44 @@
 #else
 #define POISON ((unsigned) 0xdeadbeef)
 #endif
-#define POISON_SIZE    32
+#define POISON_SIZE    64
+
+int32_t
+poison_value(void *v)
+{
+       return POISON;
+}
 
 void
 poison_mem(void *v, size_t len)
 {
        uint32_t *ip = v;
        size_t i;
+       int32_t poison;
+
+       poison = poison_value(v);
 
        if (len > POISON_SIZE)
                len = POISON_SIZE;
        len = len / sizeof(*ip);
        for (i = 0; i < len; i++)
-               ip[i] = POISON;
+               ip[i] = poison;
 }
 
 int
 poison_check(void *v, size_t len, size_t *pidx, int *pval)
 {
-
        uint32_t *ip = v;
        size_t i;
+       int32_t poison;
+
+       poison = poison_value(v);
 
        if (len > POISON_SIZE)
                len = POISON_SIZE;
        len = len / sizeof(*ip);
        for (i = 0; i < len; i++) {
-               if (ip[i] != POISON) {
+               if (ip[i] != poison) {
                        *pidx = i;
                        *pval = ip[i];
                        return 1;
Index: kern/subr_pool.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_pool.c,v
retrieving revision 1.116
diff -u -p -r1.116 subr_pool.c
--- kern/subr_pool.c    31 Mar 2013 00:03:26 -0000      1.116
+++ kern/subr_pool.c    31 Mar 2013 02:28:06 -0000
@@ -78,19 +78,11 @@ struct pool_item_header {
 };
 
 struct pool_item {
-#ifdef DIAGNOSTIC
        u_int32_t pi_magic;
-#endif
        /* Other entries use only this list entry */
        SIMPLEQ_ENTRY(pool_item)        pi_list;
 };
 
-#ifdef DEADBEEF1
-#define        PI_MAGIC DEADBEEF1
-#else
-#define        PI_MAGIC 0xdeafbeef
-#endif
-
 #ifdef POOL_DEBUG
 int    pool_debug = 1;
 #else
@@ -463,7 +455,7 @@ pool_alloc_item_header(struct pool *pp, 
                ph = pool_get(&phpool, (flags & ~(PR_WAITOK | PR_ZERO)) |
                    PR_NOWAIT);
        if (pool_debug && ph != NULL)
-               ph->ph_magic = PI_MAGIC;
+               ph->ph_magic = poison_value(ph);
        return (ph);
 }
 
@@ -638,11 +630,10 @@ startover:
 #endif
 
 #ifdef DIAGNOSTIC
-       if (pi->pi_magic != PI_MAGIC)
+       if (pi->pi_magic != poison_value(pi))
                panic("pool_do_get(%s): free list modified: "
                    "page %p; item addr %p; offset 0x%x=0x%x",
                    pp->pr_wchan, ph->ph_page, pi, 0, pi->pi_magic);
-#ifdef POOL_DEBUG
        if (pool_debug && ph->ph_magic) {
                size_t pidx;
                int pval;
@@ -655,7 +646,6 @@ startover:
                            pidx * sizeof(int), ip[pidx]);
                }
        }
-#endif /* POOL_DEBUG */
 #endif /* DIAGNOSTIC */
 
        /*
@@ -773,12 +763,10 @@ pool_do_put(struct pool *pp, void *v)
         * Return to item list.
         */
 #ifdef DIAGNOSTIC
-       pi->pi_magic = PI_MAGIC;
-#ifdef POOL_DEBUG
+       pi->pi_magic = poison_value(pi);
        if (ph->ph_magic) {
                poison_mem(pi + 1, pp->pr_size - sizeof(*pi));
        }
-#endif /* POOL_DEBUG */
 #endif /* DIAGNOSTIC */
 
        SIMPLEQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list);
@@ -922,12 +910,10 @@ pool_prime_page(struct pool *pp, caddr_t
                SIMPLEQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list);
 
 #ifdef DIAGNOSTIC
-               pi->pi_magic = PI_MAGIC;
-#ifdef POOL_DEBUG
+               pi->pi_magic = poison_value(pi);
                if (ph->ph_magic) {
                        poison_mem(pi + 1, pp->pr_size - sizeof(*pi));
                }
-#endif /* POOL_DEBUG */
 #endif /* DIAGNOSTIC */
                cp = (caddr_t)(cp + pp->pr_size);
        }
@@ -1143,7 +1129,7 @@ pool_print_pagelist(struct pool_pagelist
                    ph->ph_page, ph->ph_nmissing);
 #ifdef DIAGNOSTIC
                SIMPLEQ_FOREACH(pi, &ph->ph_itemlist, pi_list) {
-                       if (pi->pi_magic != PI_MAGIC) {
+                       if (pi->pi_magic != poison_value(pi)) {
                                (*pr)("\t\t\titem %p, magic 0x%x\n",
                                    pi, pi->pi_magic);
                        }
@@ -1298,7 +1284,7 @@ pool_chk_page(struct pool *pp, struct po
             pi = SIMPLEQ_NEXT(pi,pi_list), n++) {
 
 #ifdef DIAGNOSTIC
-               if (pi->pi_magic != PI_MAGIC) {
+               if (pi->pi_magic != poison_value(pi)) {
                        printf("%s: ", label);
                        printf("pool(%s): free list modified: "
                            "page %p; item ordinal %d; addr %p "
@@ -1306,7 +1292,6 @@ pool_chk_page(struct pool *pp, struct po
                            pp->pr_wchan, ph->ph_page, n, pi, page,
                            0, pi->pi_magic);
                }
-#ifdef POOL_DEBUG
                if (pool_debug && ph->ph_magic) {
                        size_t pidx;
                        int pval;
@@ -1320,8 +1305,6 @@ pool_chk_page(struct pool *pp, struct po
                                    page, pidx * sizeof(int), ip[pidx]);
                        }
                }
-
-#endif /* POOL_DEBUG */
 #endif /* DIAGNOSTIC */
                page =
                    (caddr_t)((u_long)pi & pp->pr_alloc->pa_pagemask);

Reply via email to