summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorotto <>2017-09-23 15:13:12 +0000
committerotto <>2017-09-23 15:13:12 +0000
commit258b17fa326a0d3afda80e2e13941090d75c2f9f (patch)
tree7053af173364fae2f857ddda82460b7abc3b5cc0 /src/lib
parent263609dd4f2b34a02f6d2e943f58b18b8eef887a (diff)
downloadopenbsd-258b17fa326a0d3afda80e2e13941090d75c2f9f.tar.gz
openbsd-258b17fa326a0d3afda80e2e13941090d75c2f9f.tar.bz2
openbsd-258b17fa326a0d3afda80e2e13941090d75c2f9f.zip
Make delayed free non-optional and make F do an extensive double free check.
ok tb@ tedu@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/malloc.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index e522e0aee5..221a876f69 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc.c,v 1.231 2017/09/12 18:36:30 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.232 2017/09/23 15:13:12 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -179,7 +179,7 @@ struct chunk_info {
179struct malloc_readonly { 179struct malloc_readonly {
180 struct dir_info *malloc_pool[_MALLOC_MUTEXES]; /* Main bookkeeping information */ 180 struct dir_info *malloc_pool[_MALLOC_MUTEXES]; /* Main bookkeeping information */
181 int malloc_mt; /* multi-threaded mode? */ 181 int malloc_mt; /* multi-threaded mode? */
182 int malloc_freenow; /* Free quickly - disable chunk rnd */ 182 int malloc_freecheck; /* Extensive double free check */
183 int malloc_freeunmap; /* mprotect free pages PROT_NONE? */ 183 int malloc_freeunmap; /* mprotect free pages PROT_NONE? */
184 int malloc_junk; /* junk fill? */ 184 int malloc_junk; /* junk fill? */
185 int malloc_realloc; /* always realloc? */ 185 int malloc_realloc; /* always realloc? */
@@ -520,11 +520,11 @@ omalloc_parseopt(char opt)
520 break; 520 break;
521#endif /* MALLOC_STATS */ 521#endif /* MALLOC_STATS */
522 case 'f': 522 case 'f':
523 mopts.malloc_freenow = 0; 523 mopts.malloc_freecheck = 0;
524 mopts.malloc_freeunmap = 0; 524 mopts.malloc_freeunmap = 0;
525 break; 525 break;
526 case 'F': 526 case 'F':
527 mopts.malloc_freenow = 1; 527 mopts.malloc_freecheck = 1;
528 mopts.malloc_freeunmap = 1; 528 mopts.malloc_freeunmap = 1;
529 break; 529 break;
530 case 'g': 530 case 'g':
@@ -605,7 +605,7 @@ omalloc_init(void)
605 for (; p != NULL && *p != '\0'; p++) { 605 for (; p != NULL && *p != '\0'; p++) {
606 switch (*p) { 606 switch (*p) {
607 case 'S': 607 case 'S':
608 for (q = "CGJ"; *q != '\0'; q++) 608 for (q = "CFGJ"; *q != '\0'; q++)
609 omalloc_parseopt(*q); 609 omalloc_parseopt(*q);
610 mopts.malloc_cache = 0; 610 mopts.malloc_cache = 0;
611 break; 611 break;
@@ -1046,10 +1046,12 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
1046 q = p + check_sz; 1046 q = p + check_sz;
1047 1047
1048 while (p < q) { 1048 while (p < q) {
1049 if (*p++ != SOME_JUNK) { 1049 if (*p != SOME_JUNK) {
1050 wrterror(d, "chunk canary corrupted %p %#tx@%#zx", 1050 wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s",
1051 ptr, p - ptr - 1, sz); 1051 ptr, p - ptr, sz, *p == SOME_FREEJUNK ?
1052 " (double free?)" : "");
1052 } 1053 }
1054 p++;
1053 } 1055 }
1054} 1056}
1055 1057
@@ -1381,13 +1383,18 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
1381 unmap(pool, p, PAGEROUND(sz), clear); 1383 unmap(pool, p, PAGEROUND(sz), clear);
1382 delete(pool, r); 1384 delete(pool, r);
1383 } else { 1385 } else {
1384 void *tmp; 1386 /* Validate and optionally canary check */
1385 int i; 1387 find_chunknum(pool, r, p, mopts.chunk_canaries);
1386 1388 if (!clear) {
1387 /* Delayed free or canaries? Extra check */ 1389 void *tmp;
1388 if (!mopts.malloc_freenow || mopts.chunk_canaries) 1390 int i;
1389 find_chunknum(pool, r, p, mopts.chunk_canaries); 1391
1390 if (!clear && !mopts.malloc_freenow) { 1392 if (mopts.malloc_freecheck) {
1393 for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++)
1394 if (p == pool->delayed_chunks[i])
1395 wrterror(pool,
1396 "double free %p", p);
1397 }
1391 if (mopts.malloc_junk && sz > 0) 1398 if (mopts.malloc_junk && sz > 0)
1392 memset(p, SOME_FREEJUNK, sz); 1399 memset(p, SOME_FREEJUNK, sz);
1393 i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK; 1400 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)
1395 p = pool->delayed_chunks[i]; 1402 p = pool->delayed_chunks[i];
1396 if (tmp == p) 1403 if (tmp == p)
1397 wrterror(pool, "double free %p", tmp); 1404 wrterror(pool, "double free %p", tmp);
1405 pool->delayed_chunks[i] = tmp;
1398 if (mopts.malloc_junk) 1406 if (mopts.malloc_junk)
1399 validate_junk(pool, p); 1407 validate_junk(pool, p);
1400 pool->delayed_chunks[i] = tmp; 1408 } else if (sz > 0)
1401 } else { 1409 memset(p, 0, sz);
1402 if ((clear || mopts.malloc_junk) && sz > 0)
1403 memset(p, clear ? 0 : SOME_FREEJUNK, sz);
1404 }
1405 if (p != NULL) { 1410 if (p != NULL) {
1406 r = find(pool, p); 1411 r = find(pool, p);
1407 if (r == NULL) 1412 if (r == NULL)
@@ -2348,7 +2353,7 @@ malloc_exit(void)
2348 snprintf(buf, sizeof(buf), 2353 snprintf(buf, sizeof(buf),
2349 "MT=%d I=%d F=%d U=%d J=%d R=%d X=%d C=%d cache=%u G=%zu\n", 2354 "MT=%d I=%d F=%d U=%d J=%d R=%d X=%d C=%d cache=%u G=%zu\n",
2350 mopts.malloc_mt, mopts.internal_funcs, 2355 mopts.malloc_mt, mopts.internal_funcs,
2351 mopts.malloc_freenow, 2356 mopts.malloc_freecheck,
2352 mopts.malloc_freeunmap, mopts.malloc_junk, 2357 mopts.malloc_freeunmap, mopts.malloc_junk,
2353 mopts.malloc_realloc, mopts.malloc_xmalloc, 2358 mopts.malloc_realloc, mopts.malloc_xmalloc,
2354 mopts.chunk_canaries, mopts.malloc_cache, 2359 mopts.chunk_canaries, mopts.malloc_cache,