diff options
author | Bosko Milekic <bmilekic@FreeBSD.org> | 2005-01-21 18:09:17 +0000 |
---|---|---|
committer | Bosko Milekic <bmilekic@FreeBSD.org> | 2005-01-21 18:09:17 +0000 |
commit | e4eb384b477fe50f3c35034be62d8bf7a04e88c9 (patch) | |
tree | e3ac68d91ce5b621ef858776db95b6901b4a7e6b /sys/kern/kern_malloc.c | |
parent | dc5ae701946a1c6edf255c5a67ad8537b6be07cc (diff) | |
download | src-e4eb384b477fe50f3c35034be62d8bf7a04e88c9.tar.gz src-e4eb384b477fe50f3c35034be62d8bf7a04e88c9.zip |
Bring in MemGuard, a very simple and small replacement allocator
designed to help detect tamper-after-free scenarios, a problem more
and more common and likely with multithreaded kernels where race
conditions are more prevalent.
Currently MemGuard can only take over malloc()/realloc()/free() for
particular (a) malloc type(s) and the code brought in with this
change manually instruments it to take over M_SUBPROC allocations
as an example. If you are planning to use it, for now you must:
1) Put "options DEBUG_MEMGUARD" in your kernel config.
2) Edit src/sys/kern/kern_malloc.c manually, look for
"XXX CHANGEME" and replace the M_SUBPROC comparison with
the appropriate malloc type (this might require additional
but small/simple code modification if, say, the malloc type
is declared out of scope).
3) Build and install your kernel. Tune vm.memguard_divisor
boot-time tunable which is used to scale how much of kmem_map
you want to allott for MemGuard's use. The default is 10,
so kmem_size/10.
ToDo:
1) Bring in a memguard(9) man page.
2) Better instrumentation (e.g., boot-time) of MemGuard taking
over malloc types.
3) Teach UMA about MemGuard to allow MemGuard to override zone
allocations too.
4) Improve MemGuard if necessary.
This work is partly based on some old patches from Ian Dowse.
Notes
Notes:
svn path=/head/; revision=140587
Diffstat (limited to 'sys/kern/kern_malloc.c')
-rw-r--r-- | sys/kern/kern_malloc.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index e794ec08e7a3..a972854a676b 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -58,6 +58,10 @@ __FBSDID("$FreeBSD$"); #include <vm/uma_int.h> #include <vm/uma_dbg.h> +#ifdef DEBUG_MEMGUARD +#include <vm/memguard.h> +#endif + #if defined(INVARIANTS) && defined(__i386__) #include <machine/cpu.h> #endif @@ -129,6 +133,12 @@ struct { {0, NULL}, }; +#ifdef DEBUG_MEMGUARD +u_int vm_memguard_divisor; +SYSCTL_UINT(_vm, OID_AUTO, memguard_divisor, CTLFLAG_RD, &vm_memguard_divisor, + 0, "(kmem_size/memguard_divisor) == memguard submap size"); +#endif + u_int vm_kmem_size; SYSCTL_UINT(_vm, OID_AUTO, kmem_size, CTLFLAG_RD, &vm_kmem_size, 0, "Size of kernel memory"); @@ -280,6 +290,13 @@ malloc(size, type, flags) if (flags & M_WAITOK) KASSERT(curthread->td_intr_nesting_level == 0, ("malloc(M_WAITOK) in interrupt context")); + +#ifdef DEBUG_MEMGUARD + /* XXX CHANGEME! */ + if (type == M_SUBPROC) + return memguard_alloc(size, flags); +#endif + if (size <= KMEM_ZMAX) { if (size & KMEM_ZMASK) size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; @@ -331,6 +348,14 @@ free(addr, type) if (addr == NULL) return; +#ifdef DEBUG_MEMGUARD + /* XXX CHANGEME! */ + if (type == M_SUBPROC) { + memguard_free(addr); + return; + } +#endif + KASSERT(type->ks_memuse > 0, ("malloc(9)/free(9) confusion.\n%s", "Probably freeing with wrong type, but maybe not here.")); @@ -389,6 +414,14 @@ realloc(addr, size, type, flags) if (addr == NULL) return (malloc(size, type, flags)); +#ifdef DEBUG_MEMGUARD +/* XXX: CHANGEME! */ +if (type == M_SUBPROC) { + slab = NULL; + alloc = size; +} else { +#endif + slab = vtoslab((vm_offset_t)addr & ~(UMA_SLAB_MASK)); /* Sanity check */ @@ -406,6 +439,10 @@ realloc(addr, size, type, flags) && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) return (addr); +#ifdef DEBUG_MEMGUARD +} +#endif + /* Allocate a new, bigger (or smaller) block */ if ((newaddr = malloc(size, type, flags)) == NULL) return (NULL); @@ -502,6 +539,22 @@ kmeminit(dummy) (vm_offset_t *)&kmemlimit, vm_kmem_size); kmem_map->system_map = 1; +#ifdef DEBUG_MEMGUARD + /* + * Initialize MemGuard if support compiled in. MemGuard is a + * 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); +#endif + uma_startup2(); for (i = 0, indx = 0; kmemzones[indx].kz_size != 0; indx++) { |