diff options
author | 2013-03-28 16:41:39 +0000 | |
---|---|---|
committer | 2013-03-28 16:41:39 +0000 | |
commit | ef2441bcf93b02ad7a090ebae81ef35f7ac914cc (patch) | |
tree | 04021fc3ce263eff9602f1f0c98265747a5cc1dc /sys | |
parent | remove excesss includes (diff) | |
download | wireguard-openbsd-ef2441bcf93b02ad7a090ebae81ef35f7ac914cc.tar.xz wireguard-openbsd-ef2441bcf93b02ad7a090ebae81ef35f7ac914cc.zip |
separate memory poisoning code to a new file and make it usable kernel wide
ok deraadt
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/kern/kern_malloc.c | 63 | ||||
-rw-r--r-- | sys/kern/subr_poison.c | 64 | ||||
-rw-r--r-- | sys/sys/systm.h | 5 |
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) |