summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortedu <tedu@openbsd.org>2013-03-28 16:41:39 +0000
committertedu <tedu@openbsd.org>2013-03-28 16:41:39 +0000
commitef2441bcf93b02ad7a090ebae81ef35f7ac914cc (patch)
tree04021fc3ce263eff9602f1f0c98265747a5cc1dc
parentremove excesss includes (diff)
downloadwireguard-openbsd-ef2441bcf93b02ad7a090ebae81ef35f7ac914cc.tar.xz
wireguard-openbsd-ef2441bcf93b02ad7a090ebae81ef35f7ac914cc.zip
separate memory poisoning code to a new file and make it usable kernel wide
ok deraadt
-rw-r--r--sys/conf/files3
-rw-r--r--sys/kern/kern_malloc.c63
-rw-r--r--sys/kern/subr_poison.c64
-rw-r--r--sys/sys/systm.h5
4 files changed, 85 insertions, 50 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 314c7aa813b..3ca2bcbae21 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.543 2013/03/26 16:39:08 tedu Exp $
+# $OpenBSD: files,v 1.544 2013/03/28 16:41:39 tedu Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -678,6 +678,7 @@ file kern/subr_evcount.c
file kern/subr_extent.c
file kern/subr_hibernate.c hibernate
file kern/subr_log.c
+file kern/subr_poison.c diagnostic
file kern/subr_pool.c
file kern/dma_alloc.c
file kern/subr_prf.c
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index c987d2dd20e..4b57892e809 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_malloc.c,v 1.97 2013/03/26 16:36:01 tedu Exp $ */
+/* $OpenBSD: kern_malloc.c,v 1.98 2013/03/28 16:41:39 tedu Exp $ */
/* $NetBSD: kern_malloc.c,v 1.15.4.2 1996/06/13 17:10:56 cgd Exp $ */
/*
@@ -132,48 +132,14 @@ const long addrmask[] = { 0,
};
/*
- * The WEIRD_ADDR is used as known text to copy into free objects so
+ * The FREELIST_MARKER is used as known text to copy into free objects so
* that modifications after frees can be detected.
*/
#ifdef DEADBEEF0
-#define WEIRD_ADDR ((unsigned) DEADBEEF0)
+#define FREELIST_MARKER ((unsigned) DEADBEEF0)
#else
-#define WEIRD_ADDR ((unsigned) 0xdeadbeef)
+#define FREELIST_MARKER ((unsigned) 0xdeadbeef)
#endif
-#define POISON_SIZE 32
-
-static void
-poison(void *v, size_t len)
-{
- uint32_t *ip = v;
- size_t i;
-
- if (len > POISON_SIZE)
- len = POISON_SIZE;
- len = len / sizeof(*ip);
- for (i = 0; i < len; i++) {
- ip[i] = WEIRD_ADDR;
- }
-}
-
-static size_t
-poison_check(void *v, size_t len)
-{
-
- uint32_t *ip = v;
- size_t i;
-
- if (len > POISON_SIZE)
- len = POISON_SIZE;
- len = len / sizeof(*ip);
- for (i = 0; i < len; i++) {
- if (ip[i] != WEIRD_ADDR) {
- return i;
- }
- }
- return -1;
-}
-
#endif /* DIAGNOSTIC */
@@ -195,7 +161,6 @@ malloc(unsigned long size, int type, int flags)
int s;
caddr_t va, cp;
#ifdef DIAGNOSTIC
- size_t pidx;
int freshalloc;
char *savedtype;
#endif
@@ -300,7 +265,7 @@ malloc(unsigned long size, int type, int flags)
* Copy in known text to detect modification
* after freeing.
*/
- poison(cp, allocsize);
+ poison_mem(cp, allocsize);
freep->kf_type = M_FREE;
#endif /* DIAGNOSTIC */
SIMPLEQ_INSERT_HEAD(&kbp->kb_freelist, freep, kf_flist);
@@ -337,18 +302,19 @@ malloc(unsigned long size, int type, int flags)
}
}
- /* Fill the fields that we've used with WEIRD_ADDR */
- poison(freep, sizeof(*freep));
+ /* Fill the fields that we've used with poison */
+ poison_mem(freep, sizeof(*freep));
/* and check that the data hasn't been modified. */
if (freshalloc == 0) {
- if ((pidx = poison_check(va, allocsize)) != -1) {
- printf("%s %zd of object %p size 0x%lx %s %s"
+ size_t pidx;
+ int pval;
+ if (poison_check(va, allocsize, &pidx, &pval)) {
+ panic("%s %zd of object %p size 0x%lx %s %s"
" (0x%x != 0x%x)\n",
"Data modified on freelist: word",
pidx, va, size, "previous type",
- savedtype, ((int32_t*)va)[pidx], WEIRD_ADDR);
- panic("boom");
+ savedtype, ((int32_t*)va)[pidx], pval);
}
}
@@ -447,7 +413,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 == WEIRD_ADDR) {
+ if (freep->kf_spare0 == FREELIST_MARKER) {
struct kmem_freelist *fp;
SIMPLEQ_FOREACH(fp, &kbp->kb_freelist, kf_flist) {
if (addr != fp)
@@ -462,7 +428,8 @@ free(void *addr, int type)
* so we can list likely culprit if modification is detected
* when the object is reallocated.
*/
- poison(addr, size);
+ poison_mem(addr, size);
+ freep->kf_spare0 = FREELIST_MARKER;
freep->kf_type = type;
#endif /* DIAGNOSTIC */
diff --git a/sys/kern/subr_poison.c b/sys/kern/subr_poison.c
new file mode 100644
index 00000000000..f3bf077ff6a
--- /dev/null
+++ b/sys/kern/subr_poison.c
@@ -0,0 +1,64 @@
+/* $OpenBSD */
+/*
+ * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+/*
+ * The POISON is used as known text to copy into free objects so
+ * that modifications after frees can be detected.
+ */
+#ifdef DEADBEEF0
+#define POISON ((unsigned) DEADBEEF0)
+#else
+#define POISON ((unsigned) 0xdeadbeef)
+#endif
+#define POISON_SIZE 32
+
+void
+poison_mem(void *v, size_t len)
+{
+ uint32_t *ip = v;
+ size_t i;
+
+ if (len > POISON_SIZE)
+ len = POISON_SIZE;
+ len = len / sizeof(*ip);
+ for (i = 0; i < len; i++)
+ ip[i] = POISON;
+}
+
+int
+poison_check(void *v, size_t len, size_t *pidx, int *pval)
+{
+
+ uint32_t *ip = v;
+ size_t i;
+
+ if (len > POISON_SIZE)
+ len = POISON_SIZE;
+ len = len / sizeof(*ip);
+ for (i = 0; i < len; i++) {
+ if (ip[i] != POISON) {
+ *pidx = i;
+ *pval = ip[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 71117f8bd56..70164114f10 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systm.h,v 1.95 2013/02/09 20:56:35 miod Exp $ */
+/* $OpenBSD: systm.h,v 1.96 2013/03/28 16:41:39 tedu Exp $ */
/* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */
/*-
@@ -187,6 +187,9 @@ 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)