Patch to further harden glibc malloc metadata against 1-byte overflows

Chris Evans scarybeasts@gmail.com
Thu Mar 16 16:55:00 GMT 2017


Hi,

[This is a resend of a private conversation started with Florian]

Back in 2014, we landed a malloc hardening measure against 1-byte
overflows. Here is a reference:

https://www.sourceware.org/ml/glibc-bugs/2014-09/msg00181.html

Since then, there's been this really interesting piece of work that
exploited Chrome OS using a 1-byte overflow to attack glibc malloc()
metadata in a different way:

https://googleprojectzero.blogspot.com/2016/12/chrome-os-exploit-one-byte-overflow-and.html

It has been bothering me that there's still a known, generic way to
attack 1-byte overflows in glibc malloc(). So I put some thought into
whether the situation can be cleanly detected and prevented.
It can. I've attached a 2-line patch (malloc.c.diff) that cleanly
detects and aborts on the condition. I've also attached an old test
case I had for this issue
(shrink_free_hole_alloc_overlap_consolidate_backward.c). Without the
patch, the program exits normally, having aliased a couple of heap
chunks. With the patch, the program exits with something like "***
Error in `./a.out': corrupted size vs. prev_size: 0x00000000022a0400
***"

I would be very excited to see this patch land :) I think it shuts
down a known, significant mitigation bypass. I also worry that if
there remain any serious bugs in important Linux services, they are
likely to bias towards subtle "1-byte overflows" and the like, which
can currently be exploited as demonstrated by the blog post above.
This patch can't defend against more powerful corruption primitives,
such as more arbitrary overflows or multiple overflows, but I think
it's a step forward for 1-byte overflows and particularly 1-byte NUL
overflows.


Cheers
Chris
-------------- next part --------------
--- .pc/test.patch/malloc/malloc.c	2017-03-14 17:50:26.000000000 -0700
+++ malloc/malloc.c	2017-03-14 23:33:27.241466106 -0700
@@ -1409,6 +1409,8 @@
 
 /* Take a chunk off a bin list */
 #define unlink(AV, P, BK, FD) {                                            \
+    if (__builtin_expect (chunksize(P) != next_chunk(P)->prev_size, 0))	      \
+      malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV);  \
     FD = P->fd;								      \
     BK = P->bk;								      \
     if (__builtin_expect (FD->bk != P || BK->fd != P, 0))		      \
-------------- next part --------------
A non-text attachment was scrubbed...
Name: shrink_free_hole_alloc_overlap_consolidate_backward.c
Type: text/x-csrc
Size: 2015 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20170316/536d79b8/attachment.bin>


More information about the Libc-alpha mailing list