diff options
author | otto <> | 2018-01-28 13:41:48 +0000 |
---|---|---|
committer | otto <> | 2018-01-28 13:41:48 +0000 |
commit | 0fdd68e79323c32811255f4f326d3a2a1e136165 (patch) | |
tree | 78153bc2cbe6c97664fab850227401171eced9d8 | |
parent | 61b1ba1dd4145a63b5348c8754eca8b7aead54d1 (diff) | |
download | openbsd-0fdd68e79323c32811255f4f326d3a2a1e136165.tar.gz openbsd-0fdd68e79323c32811255f4f326d3a2a1e136165.tar.bz2 openbsd-0fdd68e79323c32811255f4f326d3a2a1e136165.zip |
- An error in the multithreaded case could print the wrong function name
- Start with a full page of struct region_info's
- Save an mprotect in the init code: allocate 3 pages with none and
make the middle page r/w instead of a r/w allocation and two calls to make the
guard pages none
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 8778bf1410..663d0877ae 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.242 2018/01/26 19:14:51 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.243 2018/01/28 13:41:48 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> |
@@ -62,7 +62,7 @@ | |||
62 | #define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT) | 62 | #define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT) |
63 | #define MALLOC_MAXCACHE 256 | 63 | #define MALLOC_MAXCACHE 256 |
64 | #define MALLOC_DELAYED_CHUNK_MASK 15 | 64 | #define MALLOC_DELAYED_CHUNK_MASK 15 |
65 | #define MALLOC_INITIAL_REGIONS 512 | 65 | #define MALLOC_INITIAL_REGIONS (MALLOC_PAGESIZE / sizeof(struct region_info)) |
66 | #define MALLOC_DEFAULT_CACHE 64 | 66 | #define MALLOC_DEFAULT_CACHE 64 |
67 | #define MALLOC_CHUNK_LISTS 4 | 67 | #define MALLOC_CHUNK_LISTS 4 |
68 | #define CHUNK_CHECK_LENGTH 32 | 68 | #define CHUNK_CHECK_LENGTH 32 |
@@ -93,6 +93,9 @@ | |||
93 | #define MMAP(sz) mmap(NULL, (sz), PROT_READ | PROT_WRITE, \ | 93 | #define MMAP(sz) mmap(NULL, (sz), PROT_READ | PROT_WRITE, \ |
94 | MAP_ANON | MAP_PRIVATE, -1, 0) | 94 | MAP_ANON | MAP_PRIVATE, -1, 0) |
95 | 95 | ||
96 | #define MMAPNONE(sz) mmap(NULL, (sz), PROT_NONE, \ | ||
97 | MAP_ANON | MAP_PRIVATE, -1, 0) | ||
98 | |||
96 | #define MMAPA(a,sz) mmap((a), (sz), PROT_READ | PROT_WRITE, \ | 99 | #define MMAPA(a,sz) mmap((a), (sz), PROT_READ | PROT_WRITE, \ |
97 | MAP_ANON | MAP_PRIVATE, -1, 0) | 100 | MAP_ANON | MAP_PRIVATE, -1, 0) |
98 | 101 | ||
@@ -449,7 +452,7 @@ omalloc_init(void) | |||
449 | static void | 452 | static void |
450 | omalloc_poolinit(struct dir_info **dp) | 453 | omalloc_poolinit(struct dir_info **dp) |
451 | { | 454 | { |
452 | void *p; | 455 | char *p; |
453 | size_t d_avail, regioninfo_size; | 456 | size_t d_avail, regioninfo_size; |
454 | struct dir_info *d; | 457 | struct dir_info *d; |
455 | int i, j; | 458 | int i, j; |
@@ -459,13 +462,11 @@ omalloc_poolinit(struct dir_info **dp) | |||
459 | * randomise offset inside the page at which the dir_info | 462 | * randomise offset inside the page at which the dir_info |
460 | * lies (subject to alignment by 1 << MALLOC_MINSHIFT) | 463 | * lies (subject to alignment by 1 << MALLOC_MINSHIFT) |
461 | */ | 464 | */ |
462 | if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) | 465 | if ((p = MMAPNONE(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED) |
463 | wrterror(NULL, "malloc init mmap failed"); | 466 | wrterror(NULL, "malloc init mmap failed"); |
464 | mprotect(p, MALLOC_PAGESIZE, PROT_NONE); | 467 | mprotect(p + MALLOC_PAGESIZE, DIR_INFO_RSZ, PROT_READ | PROT_WRITE); |
465 | mprotect((char *)p + MALLOC_PAGESIZE + DIR_INFO_RSZ, | ||
466 | MALLOC_PAGESIZE, PROT_NONE); | ||
467 | d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT; | 468 | d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT; |
468 | d = (struct dir_info *)((char *)p + MALLOC_PAGESIZE + | 469 | d = (struct dir_info *)(p + MALLOC_PAGESIZE + |
469 | (arc4random_uniform(d_avail) << MALLOC_MINSHIFT)); | 470 | (arc4random_uniform(d_avail) << MALLOC_MINSHIFT)); |
470 | 471 | ||
471 | rbytes_init(d); | 472 | rbytes_init(d); |
@@ -1275,6 +1276,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) | |||
1275 | { | 1276 | { |
1276 | struct dir_info *pool; | 1277 | struct dir_info *pool; |
1277 | struct region_info *r; | 1278 | struct region_info *r; |
1279 | char *saved_function; | ||
1278 | size_t sz; | 1280 | size_t sz; |
1279 | int i; | 1281 | int i; |
1280 | 1282 | ||
@@ -1291,12 +1293,15 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) | |||
1291 | _MALLOC_LOCK(pool->mutex); | 1293 | _MALLOC_LOCK(pool->mutex); |
1292 | pool->active++; | 1294 | pool->active++; |
1293 | r = find(pool, p); | 1295 | r = find(pool, p); |
1294 | if (r != NULL) | 1296 | if (r != NULL) { |
1297 | saved_function = pool->func; | ||
1298 | pool->func = argpool->func; | ||
1295 | break; | 1299 | break; |
1300 | } | ||
1296 | } | 1301 | } |
1297 | } | 1302 | } |
1298 | if (r == NULL) | 1303 | if (r == NULL) |
1299 | wrterror(pool, "bogus pointer (double free?) %p", p); | 1304 | wrterror(argpool, "bogus pointer (double free?) %p", p); |
1300 | } | 1305 | } |
1301 | 1306 | ||
1302 | REALSIZE(sz, r); | 1307 | REALSIZE(sz, r); |
@@ -1388,6 +1393,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz) | |||
1388 | 1393 | ||
1389 | if (argpool != pool) { | 1394 | if (argpool != pool) { |
1390 | pool->active--; | 1395 | pool->active--; |
1396 | pool->func = saved_function; | ||
1391 | _MALLOC_UNLOCK(pool->mutex); | 1397 | _MALLOC_UNLOCK(pool->mutex); |
1392 | _MALLOC_LOCK(argpool->mutex); | 1398 | _MALLOC_LOCK(argpool->mutex); |
1393 | argpool->active++; | 1399 | argpool->active++; |
@@ -1466,6 +1472,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) | |||
1466 | struct chunk_info *info; | 1472 | struct chunk_info *info; |
1467 | size_t oldsz, goldsz, gnewsz; | 1473 | size_t oldsz, goldsz, gnewsz; |
1468 | void *q, *ret; | 1474 | void *q, *ret; |
1475 | char *saved_function; | ||
1469 | int i; | 1476 | int i; |
1470 | uint32_t chunknum; | 1477 | uint32_t chunknum; |
1471 | 1478 | ||
@@ -1486,12 +1493,15 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f) | |||
1486 | _MALLOC_LOCK(pool->mutex); | 1493 | _MALLOC_LOCK(pool->mutex); |
1487 | pool->active++; | 1494 | pool->active++; |
1488 | r = find(pool, p); | 1495 | r = find(pool, p); |
1489 | if (r != NULL) | 1496 | if (r != NULL) { |
1497 | saved_function = pool->func; | ||
1498 | pool->func = argpool->func; | ||
1490 | break; | 1499 | break; |
1500 | } | ||
1491 | } | 1501 | } |
1492 | } | 1502 | } |
1493 | if (r == NULL) | 1503 | if (r == NULL) |
1494 | wrterror(pool, "bogus pointer (double free?) %p", p); | 1504 | wrterror(argpool, "bogus pointer (double free?) %p", p); |
1495 | } | 1505 | } |
1496 | if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { | 1506 | if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { |
1497 | errno = ENOMEM; | 1507 | errno = ENOMEM; |
@@ -1643,6 +1653,7 @@ gotit: | |||
1643 | done: | 1653 | done: |
1644 | if (argpool != pool) { | 1654 | if (argpool != pool) { |
1645 | pool->active--; | 1655 | pool->active--; |
1656 | pool->func = saved_function; | ||
1646 | _MALLOC_UNLOCK(pool->mutex); | 1657 | _MALLOC_UNLOCK(pool->mutex); |
1647 | _MALLOC_LOCK(argpool->mutex); | 1658 | _MALLOC_LOCK(argpool->mutex); |
1648 | argpool->active++; | 1659 | argpool->active++; |