Re: Stack growth direction to thwart buffer overflow attacks

From: Bernd Paysan (
Date: 08/13/03

Date: Wed, 13 Aug 2003 14:12:52 +0200

John Cochran wrote:
> You can just as easily have the heap grow downwards. Therefore there is
> no reason to object to an upward-growing stack on that basis.

You can even have a heap that grows upward and downward, e.g. one side for
fixed location objects, and the other for dangling pointers, which can be

However, growing the stack upwards doesn't help a bit, since usually buffer
overflows have both a caller (to return to), and a callee (to be returned
from), and the exploit now would use the callee's return (e.g. return from

The only cure for buffer overflows is to cure the buffer overflow itself.
There are other possibilities to cure symptoms, which more or less fail to
deliver security:

* have a separate stack for buffers - may be exploited by a buffer overflow
writing into another buffer which contains commands or configuration stuff.

* separate return stack: still exploitable if you have object or function
pointers as local variables.

* non-executable stack or w^x pages - fails completely, since you can also
use threaded code (ret is goto *sp++, threaded code is goto *ip++, so
sp=ip), using libc as entry point. You'll find enough parameter cleanup
codes followed by ret to make this sort of attack feasible; and after all:
all you need is to make your malicious code executable, which is just a
single OS call away.

* guard markers: exploiter writes the guard markers himself. This can be
made tough since you could have a random guard marker per process, and even
a 32 bit word means that you have to do 2G attacks on average until you

Guard markers for buffers are a good way to catch overflows, anyway. I use
weak guards in my heap: each buffer has its length before and afterwards
(and for dangling pointers a back-pointer). The heap's integrity is checked
periodically. This works well against inadventent buffer overflows, but
won't work for exploits. The back-pointer of dangling pointers could help,
since for integrity, this has to be a loop (back-pointer points to
forward-pointer); and the attacker often won't be able to fake both of

Bernd Paysan
"If you want it done right, you have to do it yourself"