flak rss random

my stack protector wasn't working

A little while ago I asked is your stack protector working? It was supposed to be a rhetorical question. It wasn’t. In a major failing to consider all the possibilities, I overlooked the fact that I was testing i386 and not amd64. It didn’t take long for Peter Philipp to test amd64. Back to the drawing board.

welcome to the jungle

First thing to do was confirm the report. Copy the test case over to an amd64 machine, and boom, confirmed. Or rather, no boom. Next I asked some other OpenBSD developers who actually know things. They were able to confirm and explain the problem. The amd64 ABI requires that any array larger than 16 bytes is aligned to 16 bytes, regardless of the alignment of the underlying type. As explained by the 4th footnote on page 13, this lets the NSA craft more reliable exploits. All there in the manual.

Now that we know the problem, what can we do about it? We invent our own ABI and fix the compiler.

heart of darkness

Just finding the source to gcc on OpenBSD is a bit of an adventure because over the years multiple versions have existed simultaneously in the source tree. For gcc4 archs like amd64, the Makefile lives in src/gnu/usr.bin/cc but the source itself is in src/gnu/gcc. We’re looking for the backend file in the gcc/gcc/config directory for amd64. It’s called i386.c.

A quick trepanation to let the poison out:

Index: i386/i386.c
===================================================================
RCS file: /cvs/src/gnu/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.3
diff -u -p -r1.3 i386.c
--- i386/i386.c 11 May 2010 16:56:08 -0000      1.3
+++ i386/i386.c 16 Dec 2013 03:06:11 -0000
@@ -14046,7 +14046,7 @@ ix86_local_alignment (tree type, int ali
 {
   /* x86-64 ABI requires arrays greater than 16 bytes to be aligned
      to 16byte boundary.  */
-  if (TARGET_64BIT)
+  if (0 && TARGET_64BIT)
     {
       if (AGGREGATE_TYPE_P (type)
           && TYPE_SIZE (type)

Rebuild gcc. Rebuild everything else. Reboot. Looking good. Rebuild our test case.

$ echo 12345678901234567890123456789012 | ./scanf
12345678901234567890123456789012 0xabad1dea
Abort trap (core dumped) 

Looking real good. I also checked a few other array sizes like 31 and 33 to make sure one byte overflows were detected. They were. Once the backend stops enforcing artificial alignment restrictions, ProPolice can arrange the array so even the tiniest overflows are detected.

Posted 16 Dec 2013 03:22 by tedu Updated: 10 Oct 2014 00:34
Tagged: c openbsd programming