- An error in the multithreaded case could print the wrong function name
authorotto <otto@openbsd.org>
Sun, 28 Jan 2018 13:41:48 +0000 (13:41 +0000)
committerotto <otto@openbsd.org>
Sun, 28 Jan 2018 13:41:48 +0000 (13:41 +0000)
- 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

lib/libc/stdlib/malloc.c

index 8778bf1..663d087 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: malloc.c,v 1.242 2018/01/26 19:14:51 otto Exp $       */
+/*     $OpenBSD: malloc.c,v 1.243 2018/01/28 13:41:48 otto Exp $       */
 /*
  * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
  * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -62,7 +62,7 @@
 #define MALLOC_MAXCHUNK                (1 << MALLOC_MAXSHIFT)
 #define MALLOC_MAXCACHE                256
 #define MALLOC_DELAYED_CHUNK_MASK      15
-#define MALLOC_INITIAL_REGIONS 512
+#define MALLOC_INITIAL_REGIONS (MALLOC_PAGESIZE / sizeof(struct region_info))
 #define MALLOC_DEFAULT_CACHE   64
 #define MALLOC_CHUNK_LISTS     4
 #define CHUNK_CHECK_LENGTH     32
@@ -93,6 +93,9 @@
 #define MMAP(sz)       mmap(NULL, (sz), PROT_READ | PROT_WRITE, \
     MAP_ANON | MAP_PRIVATE, -1, 0)
 
+#define MMAPNONE(sz)   mmap(NULL, (sz), PROT_NONE, \
+    MAP_ANON | MAP_PRIVATE, -1, 0)
+
 #define MMAPA(a,sz)    mmap((a), (sz), PROT_READ | PROT_WRITE, \
     MAP_ANON | MAP_PRIVATE, -1, 0)
 
@@ -449,7 +452,7 @@ omalloc_init(void)
 static void
 omalloc_poolinit(struct dir_info **dp)
 {
-       void *p;
+       char *p;
        size_t d_avail, regioninfo_size;
        struct dir_info *d;
        int i, j;
@@ -459,13 +462,11 @@ omalloc_poolinit(struct dir_info **dp)
         * randomise offset inside the page at which the dir_info
         * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
         */
-       if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
+       if ((p = MMAPNONE(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
                wrterror(NULL, "malloc init mmap failed");
-       mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
-       mprotect((char *)p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
-           MALLOC_PAGESIZE, PROT_NONE);
+       mprotect(p + MALLOC_PAGESIZE, DIR_INFO_RSZ, PROT_READ | PROT_WRITE);
        d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
-       d = (struct dir_info *)((char *)p + MALLOC_PAGESIZE +
+       d = (struct dir_info *)(p + MALLOC_PAGESIZE +
            (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
 
        rbytes_init(d);
@@ -1275,6 +1276,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
 {
        struct dir_info *pool;
        struct region_info *r;
+       char *saved_function;
        size_t sz;
        int i;
 
@@ -1291,12 +1293,15 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
                                _MALLOC_LOCK(pool->mutex);
                                pool->active++;
                                r = find(pool, p);
-                               if (r != NULL)
+                               if (r != NULL) {
+                                       saved_function = pool->func;
+                                       pool->func = argpool->func;
                                        break;
+                               }
                        }
                }
                if (r == NULL)
-                       wrterror(pool, "bogus pointer (double free?) %p", p);
+                       wrterror(argpool, "bogus pointer (double free?) %p", p);
        }
 
        REALSIZE(sz, r);
@@ -1388,6 +1393,7 @@ ofree(struct dir_info *argpool, void *p, int clear, int check, size_t argsz)
 
        if (argpool != pool) {
                pool->active--;
+               pool->func = saved_function;
                _MALLOC_UNLOCK(pool->mutex);
                _MALLOC_LOCK(argpool->mutex);
                argpool->active++;
@@ -1466,6 +1472,7 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
        struct chunk_info *info;
        size_t oldsz, goldsz, gnewsz;
        void *q, *ret;
+       char *saved_function;
        int i;
        uint32_t chunknum;
 
@@ -1486,12 +1493,15 @@ orealloc(struct dir_info *argpool, void *p, size_t newsz, void *f)
                                _MALLOC_LOCK(pool->mutex);
                                pool->active++;
                                r = find(pool, p);
-                               if (r != NULL)
+                               if (r != NULL) {
+                                       saved_function = pool->func;
+                                       pool->func = argpool->func;
                                        break;
+                               }
                        }
                }
                if (r == NULL)
-                       wrterror(pool, "bogus pointer (double free?) %p", p);
+                       wrterror(argpool, "bogus pointer (double free?) %p", p);
        }
        if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
                errno = ENOMEM;
@@ -1643,6 +1653,7 @@ gotit:
 done:
        if (argpool != pool) {
                pool->active--;
+               pool->func = saved_function;
                _MALLOC_UNLOCK(pool->mutex);
                _MALLOC_LOCK(argpool->mutex);
                argpool->active++;