diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/stdlib/malloc.3 | 20 | ||||
-rw-r--r-- | lib/libc/stdlib/malloc.c | 32 |
2 files changed, 33 insertions, 19 deletions
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3 index 4957591eefd..d8936260510 100644 --- a/lib/libc/stdlib/malloc.3 +++ b/lib/libc/stdlib/malloc.3 @@ -30,9 +30,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: malloc.3,v 1.132 2023/04/17 05:45:06 jmc Exp $ +.\" $OpenBSD: malloc.3,v 1.133 2023/06/04 06:58:33 otto Exp $ .\" -.Dd $Mdocdate: April 17 2023 $ +.Dd $Mdocdate: June 4 2023 $ .Dt MALLOC 3 .Os .Sh NAME @@ -314,7 +314,7 @@ Increase the junk level by one if it is smaller than 2. Decrease the junk level by one if it is larger than 0. Junking writes some junk bytes into the area allocated. Junk is bytes of 0xdb when allocating; -freed chunks are filled with 0xdf. +freed allocations are filled with 0xdf. By default the junk level is 1: after free, small chunks are completely junked; for pages the first part is junked. @@ -628,22 +628,24 @@ An attempt to .Fn free or reallocate an unallocated pointer was made. -.It Dq chunk is already free -There was an attempt to free a chunk that had already been freed. +.It Dq double free +There was an attempt to free an allocation that had already been freed. .It Dq write after free -A chunk has been modified after it was freed. +An allocation has been modified after it was freed. .It Dq modified chunk-pointer The pointer passed to .Fn free or a reallocation function has been modified. -.It Dq chunk canary corrupted address offset@length +.It Dq canary corrupted address offset@length A byte after the requested size has been overwritten, indicating a heap overflow. The offset at which corruption was detected is printed before the @, and the requested length of the allocation after the @. -.It Dq recorded old size oldsize != size +.It Dq recorded size oldsize inconsistent with size .Fn recallocarray -has detected that the given old size does not equal the recorded size in its +or +.Fn freezero +has detected that the given old size does not match the recorded size in its meta data. Enabling option .Cm C diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 316ae4f484d..c4196c74ed0 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.284 2023/05/27 04:33:00 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.285 2023/06/04 06:58:33 otto Exp $ */ /* * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> @@ -977,6 +977,10 @@ omalloc_make_chunks(struct dir_info *d, u_int bucket, u_int listnum) NULL)) goto err; LIST_INSERT_HEAD(&d->chunk_dir[bucket][listnum], bp, entries); + + if (bucket > 0 && d->malloc_junk != 0) + memset(pp, SOME_FREEJUNK, MALLOC_PAGESIZE); + return bp; err: @@ -1113,9 +1117,8 @@ found: p = (char *)bp->page + k; if (bp->bucket > 0) { - if (d->malloc_junk == 2) - memset(p, SOME_JUNK, B2SIZE(bp->bucket)); - else if (mopts.chunk_canaries) + validate_junk(d, p, B2SIZE(bp->bucket)); + if (mopts.chunk_canaries) fill_canary(p, size, B2SIZE(bp->bucket)); } return p; @@ -1134,7 +1137,7 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated) while (p < q) { if (*p != (u_char)mopts.chunk_canaries && *p != SOME_JUNK) { - wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s", + wrterror(d, "canary corrupted %p %#tx@%#zx%s", ptr, p - ptr, sz, *p == SOME_FREEJUNK ? " (double free?)" : ""); } @@ -1157,7 +1160,7 @@ find_chunknum(struct dir_info *d, struct chunk_info *info, void *ptr, int check) wrterror(d, "modified chunk-pointer %p", ptr); if (info->bits[chunknum / MALLOC_BITS] & (1U << (chunknum % MALLOC_BITS))) - wrterror(d, "chunk is already free %p", ptr); + wrterror(d, "double free %p", ptr); if (check && info->bucket > 0) { validate_canary(d, ptr, info->bits[info->offset + chunknum], B2SIZE(info->bucket)); @@ -1924,13 +1927,22 @@ orecallocarray(struct dir_info **argpool, void *p, size_t oldsize, uint32_t chunknum = find_chunknum(pool, info, p, 0); if (info->bits[info->offset + chunknum] != oldsize) - wrterror(pool, "recorded old size %hu != %zu", + wrterror(pool, "recorded size %hu != %zu", info->bits[info->offset + chunknum], oldsize); + } else { + if (sz < oldsize) + wrterror(pool, "chunk size %zu < %zu", + sz, oldsize); } - } else if (oldsize < (sz - mopts.malloc_guard) / 2) - wrterror(pool, "recorded old size %zu != %zu", - sz - mopts.malloc_guard, oldsize); + } else { + if (sz - mopts.malloc_guard < oldsize) + wrterror(pool, "recorded size %zu < %zu", + sz - mopts.malloc_guard, oldsize); + if (oldsize < (sz - mopts.malloc_guard) / 2) + wrterror(pool, "recorded size %zu inconsistent with %zu", + sz - mopts.malloc_guard, oldsize); + } newptr = omalloc(pool, newsize, 0, f); if (newptr == NULL) |