From 42170bf6d6b1aa24e8b524672f3bbaf280e7e7c9 Mon Sep 17 00:00:00 2001 From: mdf Date: Tue, 31 Aug 2010 16:57:58 +0000 Subject: The realloc case for memguard(9) will copy too many bytes when reallocating to a smaller-sized allocation. Fix this issue. Noticed by: alc Reviewed by: alc Approved by: zml (mentor) MFC after: 3 weeks --- sys/kern/kern_malloc.c | 11 ++--------- sys/vm/memguard.c | 25 +++++++++++++++++++++++++ sys/vm/memguard.h | 2 ++ 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 00df9dd..1e97b55 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -566,11 +566,8 @@ realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags) */ #ifdef DEBUG_MEMGUARD - if (is_memguard_addr(addr)) { - slab = NULL; - alloc = size; - goto remalloc; - } + if (is_memguard_addr(addr)) + return (memguard_realloc(addr, size, mtp, flags)); #endif #ifdef DEBUG_REDZONE @@ -595,10 +592,6 @@ realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags) return (addr); #endif /* !DEBUG_REDZONE */ -#ifdef DEBUG_MEMGUARD -remalloc: -#endif - /* Allocate a new, bigger (or smaller) block */ if ((newaddr = malloc(size, mtp, flags)) == NULL) return (NULL); diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c index c3d93e0..85893ab 100644 --- a/sys/vm/memguard.c +++ b/sys/vm/memguard.c @@ -399,6 +399,31 @@ memguard_free(void *ptr) vm_map_unlock(memguard_map); } +/* + * Re-allocate an allocation that was originally guarded. + */ +void * +memguard_realloc(void *addr, unsigned long size, struct malloc_type *mtp, + int flags) +{ + void *newaddr; + u_long old_size; + + /* + * Allocate the new block. Force the allocation to be guarded + * as the original may have been guarded through random + * chance, and that should be preserved. + */ + if ((newaddr = memguard_alloc(size, flags)) == NULL) + return (NULL); + + /* Copy over original contents. */ + old_size = *v2sizep(trunc_page((uintptr_t)addr)); + bcopy(addr, newaddr, min(size, old_size)); + memguard_free(addr); + return (newaddr); +} + int memguard_cmp(struct malloc_type *mtp, unsigned long size) { diff --git a/sys/vm/memguard.h b/sys/vm/memguard.h index ba7c2f1..25238b4 100644 --- a/sys/vm/memguard.h +++ b/sys/vm/memguard.h @@ -38,6 +38,7 @@ struct vm_map; unsigned long memguard_fudge(unsigned long, unsigned long); void memguard_init(struct vm_map *); void *memguard_alloc(unsigned long, int); +void *memguard_realloc(void *, unsigned long, struct malloc_type *, int); void memguard_free(void *); int memguard_cmp(struct malloc_type *, unsigned long); int is_memguard_addr(void *); @@ -45,6 +46,7 @@ int is_memguard_addr(void *); #define memguard_fudge(size, xxx) (size) #define memguard_init(map) do { } while (0) #define memguard_alloc(size, flags) NULL +#define memguard_realloc(a, s, mtp, f) NULL #define memguard_free(addr) do { } while (0) #define memguard_cmp(mtp, size) 0 #define is_memguard_addr(addr) 0 -- cgit v1.1