summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_malloc.c20
-rw-r--r--sys/vm/uma_dbg.c79
-rw-r--r--sys/vm/uma_dbg.h7
3 files changed, 103 insertions, 3 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index d45518a..5e48278 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -229,7 +229,25 @@ free(addr, type)
addr, mem);
if (!(slab->us_flags & UMA_SLAB_MALLOC)) {
+#ifdef INVARIANTS
+ struct malloc_type **mtp = addr;
+#endif
size = slab->us_zone->uz_size;
+#ifdef INVARIANTS
+ /*
+ * Cache a pointer to the malloc_type that most recently freed
+ * this memory here. This way we know who is most likely to
+ * have stepped on it later.
+ *
+ * This code assumes that size is a multiple of 8 bytes for
+ * 64 bit machines
+ */
+ mtp = (struct malloc_type **)
+ ((unsigned long)mtp & ~UMA_ALIGN_PTR);
+ mtp += (size - sizeof(struct malloc_type *)) /
+ sizeof(struct malloc_type *);
+ *mtp = type;
+#endif
uma_zfree_arg(slab->us_zone, addr, slab);
} else {
size = slab->us_size;
@@ -398,7 +416,7 @@ kmeminit(dummy)
kmemzones[indx].kz_zone = uma_zcreate(name, size,
#ifdef INVARIANTS
- trash_ctor, trash_dtor, trash_init, trash_fini,
+ mtrash_ctor, mtrash_dtor, mtrash_init, mtrash_fini,
#else
NULL, NULL, NULL, NULL,
#endif
diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c
index 0e71c6c..ab7e1b8 100644
--- a/sys/vm/uma_dbg.c
+++ b/sys/vm/uma_dbg.c
@@ -40,6 +40,7 @@
#include <sys/queue.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/malloc.h>
#include <machine/types.h>
@@ -111,6 +112,82 @@ trash_fini(void *mem, int size)
trash_ctor(mem, size, NULL);
}
+/*
+ * Checks an item to make sure it hasn't been overwritten since freed.
+ *
+ * Complies with standard ctor arg/return
+ *
+ */
+void
+mtrash_ctor(void *mem, int size, void *arg)
+{
+ struct malloc_type **ksp;
+ u_int32_t *p = mem;
+ int cnt;
+
+ size -= sizeof(struct malloc_type *);
+ ksp = (struct malloc_type **)mem;
+ ksp += size / sizeof(struct malloc_type *);
+ cnt = size / sizeof(uma_junk);
+
+ for (p = mem; cnt > 0; cnt--, p++)
+ if (*p != uma_junk) {
+ printf("Memory modified after free %p(%d)\n",
+ mem, size);
+ panic("Most recently used by %s\n", (*ksp == NULL)?
+ "none" : (*ksp)->ks_shortdesc);
+ }
+}
+
+/*
+ * Fills an item with predictable garbage
+ *
+ * Complies with standard dtor arg/return
+ *
+ */
+void
+mtrash_dtor(void *mem, int size, void *arg)
+{
+ int cnt;
+ u_int32_t *p;
+
+ size -= sizeof(struct malloc_type *);
+ cnt = size / sizeof(uma_junk);
+
+ for (p = mem; cnt > 0; cnt--, p++)
+ *p = uma_junk;
+}
+
+/*
+ * Fills an item with predictable garbage
+ *
+ * Complies with standard init arg/return
+ *
+ */
+void
+mtrash_init(void *mem, int size)
+{
+ struct malloc_type **ksp;
+
+ mtrash_dtor(mem, size, NULL);
+
+ ksp = (struct malloc_type **)mem;
+ ksp += (size / sizeof(struct malloc_type *)) - 1;
+ *ksp = NULL;
+}
+
+/*
+ * Checks an item to make sure it hasn't been overwritten since it was freed.
+ *
+ * Complies with standard fini arg/return
+ *
+ */
+void
+mtrash_fini(void *mem, int size)
+{
+ mtrash_ctor(mem, size, NULL);
+}
+
static uma_slab_t
uma_dbg_getslab(uma_zone_t zone, void *item)
{
@@ -170,8 +247,6 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
{
int freei;
- return;
-
if (slab == NULL) {
slab = uma_dbg_getslab(zone, item);
if (slab == NULL)
diff --git a/sys/vm/uma_dbg.h b/sys/vm/uma_dbg.h
index fed04a6..7967a44 100644
--- a/sys/vm/uma_dbg.h
+++ b/sys/vm/uma_dbg.h
@@ -43,6 +43,13 @@ void trash_ctor(void *mem, int size, void *arg);
void trash_dtor(void *mem, int size, void *arg);
void trash_init(void *mem, int size);
void trash_fini(void *mem, int size);
+
+/* For use only by malloc */
+void mtrash_ctor(void *mem, int size, void *arg);
+void mtrash_dtor(void *mem, int size, void *arg);
+void mtrash_init(void *mem, int size);
+void mtrash_fini(void *mem, int size);
+
void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item);
void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item);
OpenPOWER on IntegriCloud