diff options
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r-- | lib/libc/stdlib/malloc.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 8778bf14101..663d0877ae6 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.242 2018/01/26 19:14:51 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.243 2018/01/28 13:41:48 otto Exp $ */ /* * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> @@ -62,7 +62,7 @@ #define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT) #define MALLOC_MAXCACHE 256 #define MALLOC_DELAYED_CHUNK_MASK 15 -#define MALLOC_INITIAL_REGIONS 512 +#define MALLOC_INITIAL_REGIONS (MALLOC_PAGESIZE / sizeof(struct region_info)) #define MALLOC_DEFAULT_CACHE 64 #define MALLOC_CHUNK_LISTS 4 #define CHUNK_CHECK_LENGTH 32 @@ -93,6 +93,9 @@ #define MMAP(sz) mmap(NULL, (sz), PROT_READ | PROT_WRITE, \ MAP_ANON | MAP_PRIVATE, -1, 0) +#define MMAPNONE(sz) mmap(NULL, (sz), PROT_NONE, \ + MAP_ANON | MAP_PRIVATE, -1, 0) + #define MMAPA(a,sz) mmap((a), (sz), PROT_READ | PROT_WRITE, \ MAP_ANON | MAP_PRIVATE, -1, 0) @@ -449,7 +452,7 @@ omalloc_init(void) static void omalloc_poolinit(struct dir_info **dp) { - void *p; + char *p; size_t d_avail, regioninfo_size; struct dir_info *d; int i, j; @@ -459,13 +462,11 @@ omalloc_poolinit(struct dir_info **dp) * randomise offset inside the page at which the dir_info * lies (subject to alignment by 1 << MALLOC_MINSHIFT) */ - if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) + if ((p = MMAPNONE(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) wrterror(NULL, "malloc init mmap failed"); - mprotect(p, MALLOC_PAGESIZE, PROT_NONE); - mprotect((char *)p + MALLOC_PAGESIZE + DIR_INFO_RSZ, - MALLOC_PAGESIZE, PROT_NONE); + mprotect(p + MALLOC_PAGESIZE, DIR_INFO_RSZ, PROT_READ | PROT_WRITE); d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT; - d = (struct dir_info *)((char *)p + MALLOC_PAGESIZE + + d = (struct dir_info *)(p + MALLOC_PAGESIZE + (arc4random_uniform(d_avail) << MALLOC_MINSHIFT)); rbytes_init(d); @@ -1275,6 +1276,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) { struct dir_info *pool; struct region_info *r; + char *saved_function; size_t sz; int i; @@ -1291,12 +1293,15 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) _MALLOC_LOCK(pool->mutex); pool->active++; r = find(pool, p); - if (r != NULL) + if (r != NULL) { + saved_function = pool->func; + pool->func = argpool->func; break; + } } } if (r == NULL) - wrterror(pool, "bogus pointer (double free?) %p", p); + wrterror(argpool, "bogus pointer (double free?) %p", p); } REALSIZE(sz, r); @@ -1388,6 +1393,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) if (argpool != pool) { pool->active--; + pool->func = saved_function; _MALLOC_UNLOCK(pool->mutex); _MALLOC_LOCK(argpool->mutex); argpool->active++; @@ -1466,6 +1472,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) struct chunk_info *info; size_t oldsz, goldsz, gnewsz; void *q, *ret; + char *saved_function; int i; uint32_t chunknum; @@ -1486,12 +1493,15 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) _MALLOC_LOCK(pool->mutex); pool->active++; r = find(pool, p); - if (r != NULL) + if (r != NULL) { + saved_function = pool->func; + pool->func = argpool->func; break; + } } } if (r == NULL) - wrterror(pool, "bogus pointer (double free?) %p", p); + wrterror(argpool, "bogus pointer (double free?) %p", p); } if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { errno = ENOMEM; @@ -1643,6 +1653,7 @@ gotit: done: if (argpool != pool) { pool->active--; + pool->func = saved_function; _MALLOC_UNLOCK(pool->mutex); _MALLOC_LOCK(argpool->mutex); argpool->active++; |