summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2017-09-23 15:13:13 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2017-09-23 15:13:13 +0000
commitdf426f0f61124c8f395714703c66cb304ced11a8 (patch)
tree5a80e1b24450ca0cb6d6ee98d19cb38c0c002012 /lib/libc/stdlib/malloc.c
parent95be7fac7ccbb989bceabc2e4138a34eadf48ec2 (diff)
Make delayed free non-optional and make F do an extensive double free check.
ok tb@ tedu@
Diffstat (limited to 'lib/libc/stdlib/malloc.c')
-rw-r--r--lib/libc/stdlib/malloc.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index e522e0aee53..221a876f699 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.c,v 1.231 2017/09/12 18:36:30 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.232 2017/09/23 15:13:12 otto Exp $ */
/*
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -179,7 +179,7 @@ struct chunk_info {
struct malloc_readonly {
struct dir_info *malloc_pool[_MALLOC_MUTEXES]; /* Main bookkeeping information */
int malloc_mt; /* multi-threaded mode? */
- int malloc_freenow; /* Free quickly - disable chunk rnd */
+ int malloc_freecheck; /* Extensive double free check */
int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
int malloc_junk; /* junk fill? */
int malloc_realloc; /* always realloc? */
@@ -520,11 +520,11 @@ omalloc_parseopt(char opt)
break;
#endif /* MALLOC_STATS */
case 'f':
- mopts.malloc_freenow = 0;
+ mopts.malloc_freecheck = 0;
mopts.malloc_freeunmap = 0;
break;
case 'F':
- mopts.malloc_freenow = 1;
+ mopts.malloc_freecheck = 1;
mopts.malloc_freeunmap = 1;
break;
case 'g':
@@ -605,7 +605,7 @@ omalloc_init(void)
for (; p != NULL && *p != '\0'; p++) {
switch (*p) {
case 'S':
- for (q = "CGJ"; *q != '\0'; q++)
+ for (q = "CFGJ"; *q != '\0'; q++)
omalloc_parseopt(*q);
mopts.malloc_cache = 0;
break;
@@ -1046,10 +1046,12 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
q = p + check_sz;
while (p < q) {
- if (*p++ != SOME_JUNK) {
- wrterror(d, "chunk canary corrupted %p %#tx@%#zx",
- ptr, p - ptr - 1, sz);
+ if (*p != SOME_JUNK) {
+ wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s",
+ ptr, p - ptr, sz, *p == SOME_FREEJUNK ?
+ " (double free?)" : "");
}
+ p++;
}
}
@@ -1381,13 +1383,18 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
unmap(pool, p, PAGEROUND(sz), clear);
delete(pool, r);
} else {
- void *tmp;
- int i;
-
- /* Delayed free or canaries? Extra check */
- if (!mopts.malloc_freenow || mopts.chunk_canaries)
- find_chunknum(pool, r, p, mopts.chunk_canaries);
- if (!clear && !mopts.malloc_freenow) {
+ /* Validate and optionally canary check */
+ find_chunknum(pool, r, p, mopts.chunk_canaries);
+ if (!clear) {
+ void *tmp;
+ int i;
+
+ if (mopts.malloc_freecheck) {
+ for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++)
+ if (p == pool->delayed_chunks[i])
+ wrterror(pool,
+ "double free %p", p);
+ }
if (mopts.malloc_junk && sz > 0)
memset(p, SOME_FREEJUNK, sz);
i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK;
@@ -1395,13 +1402,11 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
p = pool->delayed_chunks[i];
if (tmp == p)
wrterror(pool, "double free %p", tmp);
+ pool->delayed_chunks[i] = tmp;
if (mopts.malloc_junk)
validate_junk(pool, p);
- pool->delayed_chunks[i] = tmp;
- } else {
- if ((clear || mopts.malloc_junk) && sz > 0)
- memset(p, clear ? 0 : SOME_FREEJUNK, sz);
- }
+ } else if (sz > 0)
+ memset(p, 0, sz);
if (p != NULL) {
r = find(pool, p);
if (r == NULL)
@@ -2348,7 +2353,7 @@ malloc_exit(void)
snprintf(buf, sizeof(buf),
"MT=%d I=%d F=%d U=%d J=%d R=%d X=%d C=%d cache=%u G=%zu\n",
mopts.malloc_mt, mopts.internal_funcs,
- mopts.malloc_freenow,
+ mopts.malloc_freecheck,
mopts.malloc_freeunmap, mopts.malloc_junk,
mopts.malloc_realloc, mopts.malloc_xmalloc,
mopts.chunk_canaries, mopts.malloc_cache,