diff options
author | 2013-03-28 16:41:39 +0000 | |
---|---|---|
committer | 2013-03-28 16:41:39 +0000 | |
commit | ef2441bcf93b02ad7a090ebae81ef35f7ac914cc (patch) | |
tree | 04021fc3ce263eff9602f1f0c98265747a5cc1dc /sys/kern | |
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/kern')
-rw-r--r-- | sys/kern/kern_malloc.c | 63 | ||||
-rw-r--r-- | sys/kern/subr_poison.c | 64 |
2 files changed, 79 insertions, 48 deletions
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; +} + |