summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/malloc.c599
1 files changed, 294 insertions, 305 deletions
diff --git a/libexec/ld.so/malloc.c b/libexec/ld.so/malloc.c
index fb93e37f06c..133cd4e59d0 100644
--- a/libexec/ld.so/malloc.c
+++ b/libexec/ld.so/malloc.c
@@ -48,7 +48,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
@@ -73,6 +73,9 @@
#define MMAP(sz) _dl_mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
+#define MMAPNONE(sz) _dl_mmap(NULL, (size_t)(sz), PROT_NONE, \
+ MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
+
#define MMAP_ERROR(p) (_dl_mmap_error(p) ? MAP_FAILED : (p))
struct region_info {
@@ -94,13 +97,13 @@ struct dir_info {
struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1][MALLOC_CHUNK_LISTS];
size_t free_regions_size; /* free pages cached */
/* free pages cache */
+ u_int rotor;
struct region_info free_regions[MALLOC_MAXCACHE];
/* delayed free chunk slots */
void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1];
size_t rbytesused; /* random bytes used */
char *func; /* current function */
u_char rbytes[256]; /* random bytes */
- u_short chunk_start;
u_int32_t canary2;
};
#define DIR_INFO_RSZ ((sizeof(struct dir_info) + MALLOC_PAGEMASK) & \
@@ -115,7 +118,7 @@ struct dir_info {
struct chunk_info {
LIST_ENTRY(chunk_info) entries;
void *page; /* pointer to the page */
- u_int32_t canary;
+ u_short canary;
u_short size; /* size of this page's chunks */
u_short shift; /* how far to shift for this size */
u_short free; /* how many free chunks */
@@ -197,136 +200,6 @@ getrbyte(struct dir_info *d)
}
/*
- * Cache maintenance. We keep at most malloc_cache pages cached.
- * If the cache is becoming full, unmap pages in the cache for real,
- * and then add the region to the cache
- * Opposed to the regular region data structure, the sizes in the
- * cache are in MALLOC_PAGESIZE units.
- */
-static void
-unmap(struct dir_info *d, void *p, size_t sz)
-{
- size_t psz = sz >> MALLOC_PAGESHIFT;
- size_t rsz, tounmap;
- struct region_info *r;
- u_int i, offset;
-
- if (sz != PAGEROUND(sz))
- wrterror("munmap round");
-
- if (psz > mopts.malloc_cache) {
- if (_dl_munmap(p, sz))
- wrterror("munmap");
- return;
- }
- tounmap = 0;
- rsz = mopts.malloc_cache - d->free_regions_size;
- if (psz > rsz)
- tounmap = psz - rsz;
- offset = getrbyte(d);
- for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) {
- r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
- if (r->p != NULL) {
- rsz = r->size << MALLOC_PAGESHIFT;
- if (_dl_munmap(r->p, rsz))
- wrterror("munmap");
- r->p = NULL;
- if (tounmap > r->size)
- tounmap -= r->size;
- else
- tounmap = 0;
- d->free_regions_size -= r->size;
- r->size = 0;
- }
- }
- if (tounmap > 0)
- wrterror("malloc cache underflow");
- for (i = 0; i < mopts.malloc_cache; i++) {
- r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
- if (r->p == NULL) {
- if (mopts.malloc_junk && !mopts.malloc_freeunmap) {
- size_t amt = mopts.malloc_junk == 1 ?
- MALLOC_MAXCHUNK : sz;
- _dl_memset(p, SOME_FREEJUNK, amt);
- }
- if (mopts.malloc_freeunmap)
- _dl_mprotect(p, sz, PROT_NONE);
- r->p = p;
- r->size = psz;
- d->free_regions_size += psz;
- break;
- }
- }
- if (i == mopts.malloc_cache)
- wrterror("malloc free slot lost");
- if (d->free_regions_size > mopts.malloc_cache)
- wrterror("malloc cache overflow");
-}
-
-static void *
-map(struct dir_info *d, size_t sz, int zero_fill)
-{
- size_t psz = sz >> MALLOC_PAGESHIFT;
- struct region_info *r, *big = NULL;
- u_int i, offset;
- void *p;
-
- if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
- d->canary1 != ~d->canary2)
- wrterror("internal struct corrupt");
- if (sz != PAGEROUND(sz)) {
- wrterror("map round");
- return MAP_FAILED;
- }
- if (psz > d->free_regions_size) {
- p = MMAP(sz);
- p = MMAP_ERROR(p);
- /* zero fill not needed */
- return p;
- }
- offset = getrbyte(d);
- for (i = 0; i < mopts.malloc_cache; i++) {
- r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
- if (r->p != NULL) {
- if (r->size == psz) {
- p = r->p;
- if (mopts.malloc_freeunmap)
- _dl_mprotect(p, sz, PROT_READ | PROT_WRITE);
- r->p = NULL;
- r->size = 0;
- d->free_regions_size -= psz;
- if (zero_fill)
- _dl_memset(p, 0, sz);
- else if (mopts.malloc_junk == 2 &&
- mopts.malloc_freeunmap)
- _dl_memset(p, SOME_FREEJUNK, sz);
- return p;
- } else if (r->size > psz)
- big = r;
- }
- }
- if (big != NULL) {
- r = big;
- p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
- if (mopts.malloc_freeunmap)
- _dl_mprotect(p, sz, PROT_READ | PROT_WRITE);
- r->size -= psz;
- d->free_regions_size -= psz;
- if (zero_fill)
- _dl_memset(p, 0, sz);
- else if (mopts.malloc_junk == 2 && mopts.malloc_freeunmap)
- _dl_memset(p, SOME_FREEJUNK, sz);
- return p;
- }
- p = MMAP(sz);
- p = MMAP_ERROR(p);
- if (d->free_regions_size > mopts.malloc_cache)
- wrterror("malloc cache");
- /* zero fill not needed */
- return p;
-}
-
-/*
* Initialize a dir_info, which should have been cleared by caller
*/
static void
@@ -355,13 +228,11 @@ omalloc_init(struct dir_info **dp)
* randomise offset inside the page at which the dir_info
* lies (subject to alignment by 1 << MALLOC_MINSHIFT)
*/
- p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2));
+ p = MMAPNONE(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2));
p = MMAP_ERROR(p);
if (p == MAP_FAILED)
wrterror("malloc init mmap failed");
- _dl_mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
- _dl_mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
- MALLOC_PAGESIZE, PROT_NONE);
+ _dl_mprotect(p + MALLOC_PAGESIZE, DIR_INFO_RSZ, PROT_READ | PROT_WRITE);
d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
_dl_arc4randombuf(&tmp, sizeof(tmp));
@@ -390,7 +261,8 @@ omalloc_init(struct dir_info **dp)
* Prevent further tampering with them.
*/
if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
- _dl_mprotect(&malloc_readonly, sizeof(malloc_readonly), PROT_READ);
+ _dl_mprotect(&malloc_readonly, sizeof(malloc_readonly),
+ PROT_READ);
}
@@ -403,7 +275,7 @@ omalloc_grow(struct dir_info *d)
size_t i;
struct region_info *p;
- if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 )
+ if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2)
return 1;
newtotal = d->regions_total * 2;
@@ -434,44 +306,6 @@ omalloc_grow(struct dir_info *d)
return 0;
}
-static struct chunk_info *
-alloc_chunk_info(struct dir_info *d, int bits)
-{
- struct chunk_info *p;
- size_t size, count;
-
- if (bits == 0)
- count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
- else
- count = MALLOC_PAGESIZE >> bits;
-
- size = howmany(count, MALLOC_BITS);
- size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
- if (mopts.chunk_canaries)
- size += count * sizeof(u_short);
- size = ALIGN(size);
-
- if (LIST_EMPTY(&d->chunk_info_list[bits])) {
- char *q;
- size_t i;
-
- q = MMAP(MALLOC_PAGESIZE);
- q = MMAP_ERROR(q);
- if (q == MAP_FAILED)
- return NULL;
- count = MALLOC_PAGESIZE / size;
- for (i = 0; i < count; i++, q += size)
- LIST_INSERT_HEAD(&d->chunk_info_list[bits],
- (struct chunk_info *)q, entries);
- }
- p = LIST_FIRST(&d->chunk_info_list[bits]);
- LIST_REMOVE(p, entries);
- _dl_memset(p, 0, size);
- p->canary = d->canary1;
- return p;
-}
-
-
/*
* The hashtable uses the assumption that p is never NULL. This holds since
* non-MAP_FIXED mappings with hint 0 start at BRKSIZ.
@@ -554,14 +388,204 @@ delete(struct dir_info *d, struct region_info *ri)
}
/*
+ * Cache maintenance. We keep at most malloc_cache pages cached.
+ * If the cache is becoming full, unmap pages in the cache for real,
+ * and then add the region to the cache
+ * Opposed to the regular region data structure, the sizes in the
+ * cache are in MALLOC_PAGESIZE units.
+ */
+static void
+unmap(struct dir_info *d, void *p, size_t sz, int junk)
+{
+ size_t psz = sz >> MALLOC_PAGESHIFT;
+ size_t rsz;
+ struct region_info *r;
+ u_int i, offset, mask;
+
+ if (sz != PAGEROUND(sz))
+ wrterror("munmap round");
+
+ rsz = mopts.malloc_cache - d->free_regions_size;
+
+ if (psz > mopts.malloc_cache) {
+ if (_dl_munmap(p, sz))
+ wrterror("munmap");
+ return;
+ }
+ offset = getrbyte(d);
+ mask = mopts.malloc_cache - 1;
+ if (psz > rsz) {
+ size_t tounmap = psz - rsz;
+ i = 0;
+ for (;;) {
+ r = &d->free_regions[(i + offset) & mask];
+ if (r->p != NULL) {
+ rsz = r->size << MALLOC_PAGESHIFT;
+ if (_dl_munmap(r->p, rsz))
+ wrterror("munmap");
+ r->p = NULL;
+ if (tounmap > r->size)
+ tounmap -= r->size;
+ else
+ tounmap = 0;
+ d->free_regions_size -= r->size;
+ if (tounmap == 0) {
+ offset = i;
+ break;
+ }
+ }
+ }
+ }
+ for (i = 0; ; i++) {
+ r = &d->free_regions[(i + offset) & mask];
+ if (r->p == NULL) {
+ if (junk && !mopts.malloc_freeunmap) {
+ size_t amt = junk == 1 ? MALLOC_MAXCHUNK : sz;
+ _dl_memset(p, SOME_FREEJUNK, amt);
+ }
+ if (mopts.malloc_freeunmap)
+ _dl_mprotect(p, sz, PROT_NONE);
+ r->p = p;
+ r->size = psz;
+ d->free_regions_size += psz;
+ break;
+ }
+ }
+ if (d->free_regions_size > mopts.malloc_cache)
+ wrterror("malloc cache overflow");
+}
+
+static void *
+map(struct dir_info *d, size_t sz, int zero_fill)
+{
+ size_t psz = sz >> MALLOC_PAGESHIFT;
+ struct region_info *r, *big = NULL;
+ u_int i;
+ void *p;
+
+ if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
+ d->canary1 != ~d->canary2)
+ wrterror("internal struct corrupt");
+ if (sz != PAGEROUND(sz)) {
+ wrterror("map round");
+ return MAP_FAILED;
+ }
+ if (psz > d->free_regions_size) {
+ p = MMAP(sz);
+ p = MMAP_ERROR(p);
+ /* zero fill not needed */
+ return p;
+ }
+ for (i = 0; i < mopts.malloc_cache; i++) {
+ r = &d->free_regions[(i + d->rotor) & (mopts.malloc_cache - 1)];
+ if (r->p != NULL) {
+ if (r->size == psz) {
+ p = r->p;
+ if (mopts.malloc_freeunmap)
+ _dl_mprotect(p, sz, PROT_READ | PROT_WRITE);
+ r->p = NULL;
+ d->free_regions_size -= psz;
+ if (zero_fill)
+ _dl_memset(p, 0, sz);
+ else if (mopts.malloc_junk == 2 &&
+ mopts.malloc_freeunmap)
+ _dl_memset(p, SOME_FREEJUNK, sz);
+ d->rotor += i + 1;
+ return p;
+ } else if (r->size > psz)
+ big = r;
+ }
+ }
+ if (big != NULL) {
+ r = big;
+ p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
+ if (mopts.malloc_freeunmap)
+ _dl_mprotect(p, sz, PROT_READ | PROT_WRITE);
+ r->size -= psz;
+ d->free_regions_size -= psz;
+ if (zero_fill)
+ _dl_memset(p, 0, sz);
+ else if (mopts.malloc_junk == 2 && mopts.malloc_freeunmap)
+ _dl_memset(p, SOME_FREEJUNK, sz);
+ return p;
+ }
+ p = MMAP(sz);
+ p = MMAP_ERROR(p);
+ if (d->free_regions_size > mopts.malloc_cache)
+ wrterror("malloc cache");
+ /* zero fill not needed */
+ return p;
+}
+
+static void
+init_chunk_info(struct dir_info *d, struct chunk_info *p, int bits)
+{
+ int i;
+
+ if (bits == 0) {
+ p->shift = MALLOC_MINSHIFT;
+ p->total = p->free = MALLOC_PAGESIZE >> p->shift;
+ p->size = 0;
+ p->offset = 0xdead;
+ } else {
+ p->shift = bits;
+ p->total = p->free = MALLOC_PAGESIZE >> p->shift;
+ p->size = 1U << bits;
+ p->offset = howmany(p->total, MALLOC_BITS);
+ }
+ p->canary = (u_short)d->canary1;
+
+ /* set all valid bits in the bitmap */
+ i = p->total - 1;
+ _dl_memset(p->bits, 0xff, sizeof(p->bits[0]) * (i / MALLOC_BITS));
+ p->bits[i / MALLOC_BITS] = (2U << (i % MALLOC_BITS)) - 1;
+}
+
+static struct chunk_info *
+alloc_chunk_info(struct dir_info *d, int bits)
+{
+ struct chunk_info *p;
+
+ if (LIST_EMPTY(&d->chunk_info_list[bits])) {
+ size_t size, count, i;
+ char *q;
+
+ if (bits == 0)
+ count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
+ else
+ count = MALLOC_PAGESIZE >> bits;
+
+ size = howmany(count, MALLOC_BITS);
+ size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
+ if (mopts.chunk_canaries)
+ size += count * sizeof(u_short);
+ size = ALIGN(size);
+
+ q = MMAP(MALLOC_PAGESIZE);
+ q = MMAP_ERROR(q);
+ if (q == MAP_FAILED)
+ return NULL;
+ count = MALLOC_PAGESIZE / size;
+
+ for (i = 0; i < count; i++, q += size)
+ LIST_INSERT_HEAD(&d->chunk_info_list[bits],
+ (struct chunk_info *)q, entries);
+ }
+ p = LIST_FIRST(&d->chunk_info_list[bits]);
+ LIST_REMOVE(p, entries);
+ if (p->shift == 0)
+ init_chunk_info(d, p, bits);
+ return p;
+}
+
+/*
* Allocate a page of chunks
*/
static struct chunk_info *
omalloc_make_chunks(struct dir_info *d, int bits, int listnum)
{
struct chunk_info *bp;
- void *pp;
- int i, k;
+ void *pp;
/* Allocate a new bucket */
pp = map(d, MALLOC_PAGESIZE, 0);
@@ -569,91 +593,77 @@ omalloc_make_chunks(struct dir_info *d, int bits, int listnum)
return NULL;
bp = alloc_chunk_info(d, bits);
- if (bp == NULL) {
- unmap(d, pp, MALLOC_PAGESIZE);
- return NULL;
- }
-
+ if (bp == NULL)
+ goto err;
/* memory protect the page allocated in the malloc(0) case */
- if (bits == 0) {
- bp->size = 0;
- bp->shift = 1;
- i = MALLOC_MINSIZE - 1;
- while (i >>= 1)
- bp->shift++;
- bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
- bp->offset = 0xdead;
- bp->page = pp;
-
- k = _dl_mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
- if (k < 0) {
- unmap(d, pp, MALLOC_PAGESIZE);
- LIST_INSERT_HEAD(&d->chunk_info_list[0], bp, entries);
- return NULL;
- }
- } else {
- bp->size = 1U << bits;
- bp->shift = bits;
- bp->total = bp->free = MALLOC_PAGESIZE >> bits;
- bp->offset = howmany(bp->total, MALLOC_BITS);
- bp->page = pp;
- }
+ if (bits == 0 && _dl_mprotect(pp, MALLOC_PAGESIZE, PROT_NONE) < 0)
+ goto err;
- /* set all valid bits in the bitmap */
- k = bp->total;
- i = 0;
+ bp = alloc_chunk_info(d, bits);
+ if (bp == NULL)
+ goto err;
+ bp->page = pp;
+
+ if (insert(d, (void *)((uintptr_t)pp | bits + 1), (uintptr_t)bp))
+ goto err;
+ LIST_INSERT_HEAD(&d->chunk_dir[bits][listnum], bp, entries);
+ return bp;
- /* Do a bunch at a time */
- for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
- bp->bits[i / MALLOC_BITS] = (u_short)~0U;
+err:
+ unmap(d, pp, MALLOC_PAGESIZE, mopts.malloc_junk);
+ return NULL;
+}
- for (; i < k; i++)
- bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS);
+static int
+find_chunksize(size_t size)
+{
+ int r;
- LIST_INSERT_HEAD(&d->chunk_dir[bits][listnum], bp, entries);
+ /* malloc(0) is special */
+ if (size == 0)
+ return 0;
- bits++;
- if ((uintptr_t)pp & bits)
- wrterror("pp & bits");
+ if (size < MALLOC_MINSIZE)
+ size = MALLOC_MINSIZE;
+ size--;
- insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp);
- return bp;
+ r = MALLOC_MINSHIFT;
+ while (size >> r)
+ r++;
+ return r;
}
+static void
+fill_canary(char *ptr, size_t sz, size_t allocated)
+{
+ size_t check_sz = allocated - sz;
+
+ if (check_sz > CHUNK_CHECK_LENGTH)
+ check_sz = CHUNK_CHECK_LENGTH;
+ _dl_memset(ptr + sz, SOME_JUNK, check_sz);
+}
/*
* Allocate a chunk
*/
static void *
-malloc_bytes(struct dir_info *d, size_t argsize)
+malloc_bytes(struct dir_info *d, size_t size)
{
- int i, j, listnum;
- size_t k, size;
- u_short u, *lp;
+ u_int i, r;
+ int j, listnum;
+ size_t k;
+ u_short *lp;
struct chunk_info *bp;
+ void *p;
if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
d->canary1 != ~d->canary2)
wrterror("internal struct corrupt");
- size = argsize;
-
- /* Don't bother with anything less than this */
- /* unless we have a malloc(0) requests */
- if (size != 0 && size < MALLOC_MINSIZE)
- size = MALLOC_MINSIZE;
-
- /* Find the right bucket */
- if (size == 0)
- j = 0;
- else {
- j = MALLOC_MINSHIFT;
- i = (size - 1) >> (MALLOC_MINSHIFT - 1);
- while (i >>= 1)
- j++;
- }
+ j = find_chunksize(size);
- listnum = getrbyte(d) % MALLOC_CHUNK_LISTS;
+ r = ((u_int)getrbyte(d) << 8) | getrbyte(d);
+ listnum = r % MALLOC_CHUNK_LISTS;
/* If it's empty, make a page more of that size chunks */
if ((bp = LIST_FIRST(&d->chunk_dir[j][listnum])) == NULL) {
bp = omalloc_make_chunks(d, j, listnum);
@@ -661,63 +671,55 @@ malloc_bytes(struct dir_info *d, size_t argsize)
return NULL;
}
- if (bp->canary != d->canary1)
+ if (bp->canary != (u_short)d->canary1)
wrterror("chunk info corrupted");
- i = d->chunk_start;
- if (bp->free > 1)
- i += getrbyte(d);
- if (i >= bp->total)
- i &= bp->total - 1;
- for (;;) {
- for (;;) {
- lp = &bp->bits[i / MALLOC_BITS];
- if (!*lp) {
- i += MALLOC_BITS;
- i &= ~(MALLOC_BITS - 1);
- if (i >= bp->total)
- i = 0;
- } else
- break;
+ i = (r / MALLOC_CHUNK_LISTS) & (bp->total - 1);
+
+ /* start somewhere in a short */
+ lp = &bp->bits[i / MALLOC_BITS];
+ if (*lp) {
+ j = i % MALLOC_BITS;
+ k = __builtin_ffs(*lp >> j);
+ if (k != 0) {
+ k += j - 1;
+ goto found;
}
- k = i % MALLOC_BITS;
- u = 1 << k;
- if (*lp & u)
- break;
- if (++i >= bp->total)
+ }
+ /* no bit halfway, go to next full short */
+ i /= MALLOC_BITS;
+ for (;;) {
+ if (++i >= bp->total / MALLOC_BITS)
i = 0;
+ lp = &bp->bits[i];
+ if (*lp) {
+ k = __builtin_ffs(*lp) - 1;
+ break;
+ }
}
- d->chunk_start += i + 1;
- *lp ^= u;
+found:
+ *lp ^= 1 << k;
/* If there are no more free, remove from free-list */
- if (!--bp->free)
+ if (--bp->free == 0)
LIST_REMOVE(bp, entries);
/* Adjust to the real offset of that chunk */
k += (lp - bp->bits) * MALLOC_BITS;
- if (mopts.chunk_canaries && argsize > 0)
- bp->bits[bp->offset + k] = argsize;
+ if (mopts.chunk_canaries && size > 0)
+ bp->bits[bp->offset + k] = size;
k <<= bp->shift;
+ p = (char *)bp->page + k;
if (bp->size > 0) {
if (mopts.malloc_junk == 2)
- _dl_memset((char *)bp->page + k, SOME_JUNK, bp->size);
- else if (mopts.chunk_canaries) {
- size_t sz = bp->size - argsize;
-
- if (sz > CHUNK_CHECK_LENGTH)
- sz = CHUNK_CHECK_LENGTH;
- _dl_memset((char *)bp->page + k + argsize, SOME_JUNK,
- sz);
- }
+ _dl_memset(p, SOME_JUNK, bp->size);
+ else if (mopts.chunk_canaries)
+ fill_canary(p, size, bp->size);
}
-
- if (mopts.malloc_junk == 2 && bp->size > 0)
- _dl_memset((char *)bp->page + k, SOME_JUNK, bp->size);
- return ((char *)bp->page + k);
+ return p;
}
static void
@@ -743,7 +745,7 @@ find_chunknum(struct dir_info *d, struct region_info *r, void *ptr, int check)
uint32_t chunknum;
info = (struct chunk_info *)r->size;
- if (info->canary != d->canary1)
+ if (info->canary != (u_short)d->canary1)
wrterror("chunk info corrupted");
/* Find the chunk number on the page */
@@ -799,7 +801,7 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
if (info->size == 0 && !mopts.malloc_freeunmap)
_dl_mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
- unmap(d, info->page, MALLOC_PAGESIZE);
+ unmap(d, info->page, MALLOC_PAGESIZE, 0);
delete(d, r);
if (info->size != 0)
@@ -809,8 +811,6 @@ free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
LIST_INSERT_HEAD(mp, info, entries);
}
-
-
static void *
omalloc(size_t sz, int zero_fill)
{
@@ -828,7 +828,7 @@ omalloc(size_t sz, int zero_fill)
return NULL;
}
if (insert(g_pool, p, sz)) {
- unmap(g_pool, p, psz);
+ unmap(g_pool, p, psz, 0);
return NULL;
}
if (mopts.malloc_guard) {
@@ -855,14 +855,9 @@ omalloc(size_t sz, int zero_fill)
else
_dl_memset(p, SOME_JUNK,
psz - mopts.malloc_guard);
- } else if (mopts.chunk_canaries) {
- size_t csz = psz - sz;
-
- if (csz > CHUNK_CHECK_LENGTH)
- csz = CHUNK_CHECK_LENGTH;
- _dl_memset((char *)p + sz - mopts.malloc_guard,
- SOME_JUNK, csz);
- }
+ } else if (mopts.chunk_canaries)
+ fill_canary(p, sz - mopts.malloc_guard,
+ psz - mopts.malloc_guard);
}
} else {
@@ -972,7 +967,7 @@ ofree(void *p)
wrterror("mprotect");
}
}
- unmap(g_pool, p, PAGEROUND(sz));
+ unmap(g_pool, p, PAGEROUND(sz), mopts.malloc_junk);
delete(g_pool, r);
} else {
void *tmp;
@@ -1171,7 +1166,7 @@ omemalign(size_t alignment, size_t sz, int zero_fill)
}
if (insert(g_pool, p, sz)) {
- unmap(g_pool, p, psz);
+ unmap(g_pool, p, psz, 0);
return NULL;
}
@@ -1187,15 +1182,9 @@ omemalign(size_t alignment, size_t sz, int zero_fill)
SOME_JUNK, psz - sz);
else
_dl_memset(p, SOME_JUNK, psz - mopts.malloc_guard);
- }
- else if (mopts.chunk_canaries) {
- size_t csz = psz - sz;
-
- if (csz > CHUNK_CHECK_LENGTH)
- csz = CHUNK_CHECK_LENGTH;
- _dl_memset((char *)p + sz - mopts.malloc_guard,
- SOME_JUNK, csz);
- }
+ } else if (mopts.chunk_canaries)
+ fill_canary(p, sz - mopts.malloc_guard,
+ psz - mopts.malloc_guard);
return p;
}