summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libc/stdlib/malloc.320
-rw-r--r--src/lib/libc/stdlib/malloc.c32
2 files changed, 33 insertions, 19 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 4957591eef..d893626051 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -30,9 +30,9 @@
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $OpenBSD: malloc.3,v 1.132 2023/04/17 05:45:06 jmc Exp $ 33.\" $OpenBSD: malloc.3,v 1.133 2023/06/04 06:58:33 otto Exp $
34.\" 34.\"
35.Dd $Mdocdate: April 17 2023 $ 35.Dd $Mdocdate: June 4 2023 $
36.Dt MALLOC 3 36.Dt MALLOC 3
37.Os 37.Os
38.Sh NAME 38.Sh NAME
@@ -314,7 +314,7 @@ Increase the junk level by one if it is smaller than 2.
314Decrease the junk level by one if it is larger than 0. 314Decrease the junk level by one if it is larger than 0.
315Junking writes some junk bytes into the area allocated. 315Junking writes some junk bytes into the area allocated.
316Junk is bytes of 0xdb when allocating; 316Junk is bytes of 0xdb when allocating;
317freed chunks are filled with 0xdf. 317freed allocations are filled with 0xdf.
318By default the junk level is 1: after free, 318By default the junk level is 1: after free,
319small chunks are completely junked; 319small chunks are completely junked;
320for pages the first part is junked. 320for pages the first part is junked.
@@ -628,22 +628,24 @@ An attempt to
628.Fn free 628.Fn free
629or 629or
630reallocate an unallocated pointer was made. 630reallocate an unallocated pointer was made.
631.It Dq chunk is already free 631.It Dq double free
632There was an attempt to free a chunk that had already been freed. 632There was an attempt to free an allocation that had already been freed.
633.It Dq write after free 633.It Dq write after free
634A chunk has been modified after it was freed. 634An allocation has been modified after it was freed.
635.It Dq modified chunk-pointer 635.It Dq modified chunk-pointer
636The pointer passed to 636The pointer passed to
637.Fn free 637.Fn free
638or a reallocation function has been modified. 638or a reallocation function has been modified.
639.It Dq chunk canary corrupted address offset@length 639.It Dq canary corrupted address offset@length
640A byte after the requested size has been overwritten, 640A byte after the requested size has been overwritten,
641indicating a heap overflow. 641indicating a heap overflow.
642The offset at which corruption was detected is printed before the @, 642The offset at which corruption was detected is printed before the @,
643and the requested length of the allocation after the @. 643and the requested length of the allocation after the @.
644.It Dq recorded old size oldsize != size 644.It Dq recorded size oldsize inconsistent with size
645.Fn recallocarray 645.Fn recallocarray
646has detected that the given old size does not equal the recorded size in its 646or
647.Fn freezero
648has detected that the given old size does not match the recorded size in its
647meta data. 649meta data.
648Enabling option 650Enabling option
649.Cm C 651.Cm C
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 316ae4f484..c4196c74ed 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.284 2023/05/27 04:33:00 otto Exp $ */ 1/* $OpenBSD: malloc.c,v 1.285 2023/06/04 06:58:33 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net>
4 * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> 4 * 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)
977 NULL)) 977 NULL))
978 goto err; 978 goto err;
979 LIST_INSERT_HEAD(&d->chunk_dir[bucket][listnum], bp, entries); 979 LIST_INSERT_HEAD(&d->chunk_dir[bucket][listnum], bp, entries);
980
981 if (bucket > 0 && d->malloc_junk != 0)
982 memset(pp, SOME_FREEJUNK, MALLOC_PAGESIZE);
983
980 return bp; 984 return bp;
981 985
982err: 986err:
@@ -1113,9 +1117,8 @@ found:
1113 1117
1114 p = (char *)bp->page + k; 1118 p = (char *)bp->page + k;
1115 if (bp->bucket > 0) { 1119 if (bp->bucket > 0) {
1116 if (d->malloc_junk == 2) 1120 validate_junk(d, p, B2SIZE(bp->bucket));
1117 memset(p, SOME_JUNK, B2SIZE(bp->bucket)); 1121 if (mopts.chunk_canaries)
1118 else if (mopts.chunk_canaries)
1119 fill_canary(p, size, B2SIZE(bp->bucket)); 1122 fill_canary(p, size, B2SIZE(bp->bucket));
1120 } 1123 }
1121 return p; 1124 return p;
@@ -1134,7 +1137,7 @@ validate_canary(struct dir_info *d, u_char *ptr, size_t sz, size_t allocated)
1134 1137
1135 while (p < q) { 1138 while (p < q) {
1136 if (*p != (u_char)mopts.chunk_canaries && *p != SOME_JUNK) { 1139 if (*p != (u_char)mopts.chunk_canaries && *p != SOME_JUNK) {
1137 wrterror(d, "chunk canary corrupted %p %#tx@%#zx%s", 1140 wrterror(d, "canary corrupted %p %#tx@%#zx%s",
1138 ptr, p - ptr, sz, 1141 ptr, p - ptr, sz,
1139 *p == SOME_FREEJUNK ? " (double free?)" : ""); 1142 *p == SOME_FREEJUNK ? " (double free?)" : "");
1140 } 1143 }
@@ -1157,7 +1160,7 @@ find_chunknum(struct dir_info *d, struct chunk_info *info, void *ptr, int check)
1157 wrterror(d, "modified chunk-pointer %p", ptr); 1160 wrterror(d, "modified chunk-pointer %p", ptr);
1158 if (info->bits[chunknum / MALLOC_BITS] & 1161 if (info->bits[chunknum / MALLOC_BITS] &
1159 (1U << (chunknum % MALLOC_BITS))) 1162 (1U << (chunknum % MALLOC_BITS)))
1160 wrterror(d, "chunk is already free %p", ptr); 1163 wrterror(d, "double free %p", ptr);
1161 if (check && info->bucket > 0) { 1164 if (check && info->bucket > 0) {
1162 validate_canary(d, ptr, info->bits[info->offset + chunknum], 1165 validate_canary(d, ptr, info->bits[info->offset + chunknum],
1163 B2SIZE(info->bucket)); 1166 B2SIZE(info->bucket));
@@ -1924,13 +1927,22 @@ orecallocarray(struct dir_info **argpool, void *p, size_t oldsize,
1924 uint32_t chunknum = find_chunknum(pool, info, p, 0); 1927 uint32_t chunknum = find_chunknum(pool, info, p, 0);
1925 1928
1926 if (info->bits[info->offset + chunknum] != oldsize) 1929 if (info->bits[info->offset + chunknum] != oldsize)
1927 wrterror(pool, "recorded old size %hu != %zu", 1930 wrterror(pool, "recorded size %hu != %zu",
1928 info->bits[info->offset + chunknum], 1931 info->bits[info->offset + chunknum],
1929 oldsize); 1932 oldsize);
1933 } else {
1934 if (sz < oldsize)
1935 wrterror(pool, "chunk size %zu < %zu",
1936 sz, oldsize);
1930 } 1937 }
1931 } else if (oldsize < (sz - mopts.malloc_guard) / 2) 1938 } else {
1932 wrterror(pool, "recorded old size %zu != %zu", 1939 if (sz - mopts.malloc_guard < oldsize)
1933 sz - mopts.malloc_guard, oldsize); 1940 wrterror(pool, "recorded size %zu < %zu",
1941 sz - mopts.malloc_guard, oldsize);
1942 if (oldsize < (sz - mopts.malloc_guard) / 2)
1943 wrterror(pool, "recorded size %zu inconsistent with %zu",
1944 sz - mopts.malloc_guard, oldsize);
1945 }
1934 1946
1935 newptr = omalloc(pool, newsize, 0, f); 1947 newptr = omalloc(pool, newsize, 0, f);
1936 if (newptr == NULL) 1948 if (newptr == NULL)