summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2012-11-02 18:18:16 +0000
committerDamien Miller <djm@cvs.openbsd.org>2012-11-02 18:18:16 +0000
commit0231a9f10e9f9cab29c6d2b2ad4907994442ae4a (patch)
treea135d7496545bccbb3893ce58235e4ab23e2aecc /lib/libc/stdlib/malloc.c
parent1cadc25e5be49ae795ccfc33d1753a17e8acb16d (diff)
Add a new malloc option 'U' => "Free unmap" that does the guarding/
unmapping of freed allocations without disabling chunk randomisation like the "Freeguard" ('F') option does. Make security 'S' option use 'U' and not 'F'. Rationale: guarding with no chunk randomisation is great for debugging use-after-free, but chunk randomisation offers better defence against "heap feng shui" style attacks that depend on carefully constructing a particular heap layout so we should leave this enabled when requesting security options.
Diffstat (limited to 'lib/libc/stdlib/malloc.c')
-rw-r--r--lib/libc/stdlib/malloc.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index c69ec8316a6..b14c7476524 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.c,v 1.147 2012/09/13 10:45:41 pirofti Exp $ */
+/* $OpenBSD: malloc.c,v 1.148 2012/11/02 18:18:15 djm Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
@@ -165,7 +165,8 @@ struct chunk_info {
struct malloc_readonly {
struct dir_info *g_pool; /* Main bookkeeping information */
int malloc_abort; /* abort() on error */
- int malloc_freeprot; /* mprotect free pages PROT_NONE? */
+ int malloc_freenow; /* Free quickly - disable chunk rnd */
+ int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
int malloc_hint; /* call madvice on free pages? */
int malloc_junk; /* junk fill? */
int malloc_move; /* move allocations to end of page? */
@@ -344,7 +345,7 @@ unmap(struct dir_info *d, void *p, size_t sz)
if (r->p == NULL) {
if (mopts.malloc_hint)
madvise(p, sz, MADV_FREE);
- if (mopts.malloc_freeprot)
+ if (mopts.malloc_freeunmap)
mprotect(p, sz, PROT_NONE);
r->p = p;
r->size = psz;
@@ -407,7 +408,7 @@ map(struct dir_info *d, size_t sz, int zero_fill)
if (r->p != NULL) {
if (r->size == psz) {
p = r->p;
- if (mopts.malloc_freeprot)
+ if (mopts.malloc_freeunmap)
mprotect(p, sz, PROT_READ | PROT_WRITE);
if (mopts.malloc_hint)
madvise(p, sz, MADV_NORMAL);
@@ -417,7 +418,7 @@ map(struct dir_info *d, size_t sz, int zero_fill)
if (zero_fill)
memset(p, 0, sz);
else if (mopts.malloc_junk &&
- mopts.malloc_freeprot)
+ mopts.malloc_freeunmap)
memset(p, SOME_FREEJUNK, sz);
return p;
} else if (r->size > psz)
@@ -427,7 +428,7 @@ map(struct dir_info *d, size_t sz, int zero_fill)
if (big != NULL) {
r = big;
p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
- if (mopts.malloc_freeprot)
+ if (mopts.malloc_freeunmap)
mprotect(p, sz, PROT_READ | PROT_WRITE);
if (mopts.malloc_hint)
madvise(p, sz, MADV_NORMAL);
@@ -435,7 +436,7 @@ map(struct dir_info *d, size_t sz, int zero_fill)
d->free_regions_size -= psz;
if (zero_fill)
memset(p, 0, sz);
- else if (mopts.malloc_junk && mopts.malloc_freeprot)
+ else if (mopts.malloc_junk && mopts.malloc_freeunmap)
memset(p, SOME_FREEJUNK, sz);
return p;
}
@@ -515,10 +516,12 @@ omalloc_init(struct dir_info **dp)
break;
#endif /* MALLOC_STATS */
case 'f':
- mopts.malloc_freeprot = 0;
+ mopts.malloc_freenow = 0;
+ mopts.malloc_freeunmap = 0;
break;
case 'F':
- mopts.malloc_freeprot = 1;
+ mopts.malloc_freenow = 1;
+ mopts.malloc_freeunmap = 1;
break;
case 'g':
mopts.malloc_guard = 0;
@@ -554,15 +557,21 @@ omalloc_init(struct dir_info **dp)
mopts.malloc_realloc = 1;
break;
case 's':
- mopts.malloc_freeprot = mopts.malloc_junk = 0;
+ mopts.malloc_freeunmap = mopts.malloc_junk = 0;
mopts.malloc_guard = 0;
mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
break;
case 'S':
- mopts.malloc_freeprot = mopts.malloc_junk = 1;
+ mopts.malloc_freeunmap = mopts.malloc_junk = 1;
mopts.malloc_guard = MALLOC_PAGESIZE;
mopts.malloc_cache = 0;
break;
+ case 'u':
+ mopts.malloc_freeunmap = 0;
+ break;
+ case 'U':
+ mopts.malloc_freeunmap = 1;
+ break;
case 'x':
mopts.malloc_xmalloc = 0;
break;
@@ -1015,7 +1024,7 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
LIST_REMOVE(info, entries);
- if (info->size == 0 && !mopts.malloc_freeprot)
+ if (info->size == 0 && !mopts.malloc_freeunmap)
mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
unmap(d, info->page, MALLOC_PAGESIZE);
@@ -1184,7 +1193,7 @@ ofree(void *p)
if (mopts.malloc_guard) {
if (sz < mopts.malloc_guard)
wrterror("guard size", NULL);
- if (!mopts.malloc_freeprot) {
+ if (!mopts.malloc_freeunmap) {
if (mprotect((char *)p + PAGEROUND(sz) -
mopts.malloc_guard, mopts.malloc_guard,
PROT_READ | PROT_WRITE))
@@ -1192,7 +1201,7 @@ ofree(void *p)
}
malloc_guarded -= mopts.malloc_guard;
}
- if (mopts.malloc_junk && !mopts.malloc_freeprot)
+ if (mopts.malloc_junk && !mopts.malloc_freeunmap)
memset(p, SOME_FREEJUNK,
PAGEROUND(sz) - mopts.malloc_guard);
unmap(g_pool, p, PAGEROUND(sz));
@@ -1203,7 +1212,7 @@ ofree(void *p)
if (mopts.malloc_junk && sz > 0)
memset(p, SOME_FREEJUNK, sz);
- if (!mopts.malloc_freeprot) {
+ if (!mopts.malloc_freenow) {
i = getrnibble();
tmp = p;
p = g_pool->delayed_chunks[i];