Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Jul 1998 20:18:57 -0400
From:      "Allen Smith" <easmith@beatrice.rutgers.edu>
To:        Ollivier Robert <roberto@keltia.freenix.fr>
Cc:        security@FreeBSD.ORG
Subject:   Re: The 99,999-bug question: Why can you execute from the stack?
Message-ID:  <9807192018.ZM18945@beatrice.rutgers.edu>
In-Reply-To: Ollivier Robert <roberto@keltia.freenix.fr>     "Re: The 99,999-bug question: Why can you execute from the stack?" (Jul 19, 11:55pm)
References:  <199807192047.OAA02264@lariat.lariat.org>  <19980719235532.A8630@keltia.freenix.fr>

next in thread | previous in thread | raw e-mail | index | archive | help
On Jul 19, 11:55pm, Ollivier Robert (possibly) wrote:
> According to Brett Glass:
> > segmentation model normally prevents this, and there's additional hardware
> > in the MMU that's supposed to be able to preclude it. Why does the OS leave
> > this gigantic hole open? Why not just close it?
> 
> As it has been said several times already, gcc itself make code on the
> stack a bit difficult to forbid. It generates code on the stack for
> "trampolines".

According to the ?guy?, Solar Developer, who wrote the linux patch, in
199704131906.QAA06271@sun1.ideal.ru:

____
About GCC trampolines -- yes, there is a problem, but in reality it turns
out to be quite easy to solve; also, nested functions, and especially
those which address gets passed somewhere else, are not common in real
world applications -- one of the reasons is that it's a GNU C extension.
Since most programs will never use the trampolines, it makes sense to run
them with non-executable stack, and enable stack execution permission for
those that really need it. This can be done automatically, by modifying
the GPF handler to switch back to the huge code segment (which covers the
stack) and re-executing the instruction, unless it was a RET. Since most
buffer overflows can only be exploited by overwriting the return address,
this will still make them unexploitable (RET has to be the instruction to
pass the control onto the stack), while C programs will normally only use
CALL, and it is extremely unlikely that some code will use RET for that
purpose (this can never happen for pure C programs compiled with GCC).
Note that such emulation won't make the things run any slower since only
one GPF per entire process life may get generated (after that the stack
remains executable for this entire process).

About me breaking the entire signal handling -- wrong, I handle this case
specially from the very beginning, by temporary switching to the huge code
segment for the time of signal handler execution. This leaves potential
buffer overflows in signal handlers exploitable, but there seems to be no
other simple way for the kernel to put the necessary return code in user
program's address space (remember, signal handlers have to return with a
plain RET, but they need to return to the kernel, so some extra code in the
user space is required, which would get jumped to by the RET, and jump into
the kernel).
____

Admittedly, I don't know enough on x86 programming to know whether or
not this will work on FreeBSD; it appears to on Linux.

	-Allen

-- 
Allen Smith				easmith@beatrice.rutgers.edu
	

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe security" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9807192018.ZM18945>