diff options
author | mdf <mdf@FreeBSD.org> | 2010-08-11 22:10:37 +0000 |
---|---|---|
committer | mdf <mdf@FreeBSD.org> | 2010-08-11 22:10:37 +0000 |
commit | 0737955344e4f99aa4ecd858ef6e507e591db2a7 (patch) | |
tree | de9dacb02fad4c45fd9ea45f38dd4fedbb294977 /sys/kern/kern_malloc.c | |
parent | d548943ae909fff2cc91f964186d557895e14bab (diff) | |
download | FreeBSD-src-0737955344e4f99aa4ecd858ef6e507e591db2a7.zip FreeBSD-src-0737955344e4f99aa4ecd858ef6e507e591db2a7.tar.gz |
Rework memguard(9) to reserve significantly more KVA to detect
use-after-free over a longer time. Also release the backing pages of
a guarded allocation at free(9) time to reduce the overhead of using
memguard(9). Allow setting and varying the malloc type at run-time.
Add knobs to allow:
- randomly guarding memory
- adding un-backed KVA guard pages to detect underflow and overflow
- a lower limit on the size of allocations that are guarded
Reviewed by: alc
Reviewed by: brueffer, Ulrich Spörlein <uqs spoerlein net> (man page)
Silence from: -arch
Approved by: zml (mentor)
MFC after: 1 month
Diffstat (limited to 'sys/kern/kern_malloc.c')
-rw-r--r-- | sys/kern/kern_malloc.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 963cf09..00df9dd 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -427,8 +427,12 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags) ("malloc(M_WAITOK) in interrupt context")); #ifdef DEBUG_MEMGUARD - if (memguard_cmp(mtp)) - return memguard_alloc(size, flags); + if (memguard_cmp(mtp, size)) { + va = memguard_alloc(size, flags); + if (va != NULL) + return (va); + /* This is unfortunate but should not be fatal. */ + } #endif #ifdef DEBUG_REDZONE @@ -493,7 +497,7 @@ free(void *addr, struct malloc_type *mtp) return; #ifdef DEBUG_MEMGUARD - if (memguard_cmp(mtp)) { + if (is_memguard_addr(addr)) { memguard_free(addr); return; } @@ -562,10 +566,11 @@ realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags) */ #ifdef DEBUG_MEMGUARD -if (memguard_cmp(mtp)) { - slab = NULL; - alloc = size; -} else { + if (is_memguard_addr(addr)) { + slab = NULL; + alloc = size; + goto remalloc; + } #endif #ifdef DEBUG_REDZONE @@ -591,7 +596,7 @@ if (memguard_cmp(mtp)) { #endif /* !DEBUG_REDZONE */ #ifdef DEBUG_MEMGUARD -} +remalloc: #endif /* Allocate a new, bigger (or smaller) block */ @@ -625,7 +630,7 @@ static void kmeminit(void *dummy) { uint8_t indx; - u_long mem_size; + u_long mem_size, tmp; int i; mtx_init(&malloc_mtx, "malloc", NULL, MTX_DEF); @@ -685,8 +690,13 @@ kmeminit(void *dummy) */ init_param3(vm_kmem_size / PAGE_SIZE); +#ifdef DEBUG_MEMGUARD + tmp = memguard_fudge(vm_kmem_size, vm_kmem_size_max); +#else + tmp = vm_kmem_size; +#endif kmem_map = kmem_suballoc(kernel_map, &kmembase, &kmemlimit, - vm_kmem_size, TRUE); + tmp, TRUE); kmem_map->system_map = 1; #ifdef DEBUG_MEMGUARD @@ -695,14 +705,7 @@ kmeminit(void *dummy) * replacement allocator used for detecting tamper-after-free * scenarios as they occur. It is only used for debugging. */ - vm_memguard_divisor = 10; - TUNABLE_INT_FETCH("vm.memguard.divisor", &vm_memguard_divisor); - - /* Pick a conservative value if provided value sucks. */ - if ((vm_memguard_divisor <= 0) || - ((vm_kmem_size / vm_memguard_divisor) == 0)) - vm_memguard_divisor = 10; - memguard_init(kmem_map, vm_kmem_size / vm_memguard_divisor); + memguard_init(kmem_map); #endif uma_startup2(); |