From 42f826b2c30d5ea8653b2c5d8553aaaf5016591c Mon Sep 17 00:00:00 2001 From: otto Date: Sat, 1 Apr 2023 18:47:51 +0000 Subject: [PATCH] Check all chunks in the delayed free list for write-after-free. Should catch more of them and closer (in time) to the WAF. ok tb@ --- lib/libc/stdlib/malloc.3 | 7 ++++--- lib/libc/stdlib/malloc.c | 26 +++++++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3 index 9bd498ab50d..b35b9220f62 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.129 2022/03/31 17:27:16 naddy Exp $ +.\" $OpenBSD: malloc.3,v 1.130 2023/04/01 18:47:51 otto Exp $ .\" -.Dd $Mdocdate: March 31 2022 $ +.Dd $Mdocdate: April 1 2023 $ .Dt MALLOC 3 .Os .Sh NAME @@ -293,7 +293,8 @@ order to have any effect. .It Cm F .Dq Freecheck . Enable more extensive double free and use after free detection. -All chunks in the delayed free list will be checked for double frees. +All chunks in the delayed free list will be checked for double frees and +write after frees. Unused pages on the freelist are read and write protected to cause a segmentation fault upon access. .It Cm G diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index c049b2da54b..2ac4b73ec07 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malloc.c,v 1.278 2023/03/25 15:22:06 otto Exp $ */ +/* $OpenBSD: malloc.c,v 1.279 2023/04/01 18:47:51 otto Exp $ */ /* * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek * Copyright (c) 2012 Matthew Dempsky @@ -1554,11 +1554,25 @@ ofree(struct dir_info **argpool, void *p, int clear, int check, size_t argsz) find_chunknum(pool, info, p, mopts.chunk_canaries); if (mopts.malloc_freecheck) { - for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++) - if (p == pool->delayed_chunks[i]) + for (i = 0; i <= MALLOC_DELAYED_CHUNK_MASK; i++) { + tmp = pool->delayed_chunks[i]; + if (tmp == p) wrterror(pool, "double free %p", p); + if (tmp != NULL) { + size_t tmpsz; + + r = find(pool, tmp); + if (r == NULL) + wrterror(pool, + "bogus pointer (" + "double free?) %p", tmp); + REALSIZE(tmpsz, r); + validate_junk(pool, tmp, tmpsz); + } + } } + if (clear && argsz > 0) explicit_bzero(p, argsz); junk_free(pool->malloc_junk, p, sz); @@ -1574,8 +1588,10 @@ ofree(struct dir_info **argpool, void *p, int clear, int check, size_t argsz) if (r == NULL) wrterror(pool, "bogus pointer (double free?) %p", p); - REALSIZE(sz, r); - validate_junk(pool, p, sz); + if (!mopts.malloc_freecheck) { + REALSIZE(sz, r); + validate_junk(pool, p, sz); + } free_bytes(pool, r, p); } } -- 2.20.1