Browse Source

Make delayed free non-optional and make F do an extensive double free check.

ok tb@ tedu@
OPENBSD_6_2
otto 7 years ago
parent
commit
3b6bc929b8
1 changed files with 26 additions and 21 deletions
  1. +26
    -21
      src/lib/libc/stdlib/malloc.c

+ 26
- 21
src/lib/libc/stdlib/malloc.c View File

@ -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,


Loading…
Cancel
Save