Re: Unexecutable Stack / Buffer Overflow Exploits...

Steve VanDevender (stevev@efn.org)
Thu, 30 Dec 1999 14:08:21 -0800 (PST)


Theodore Y. Ts'o writes:
> I will observe that by putting in some bounds checking code in strcpy,
> strncpy, memcpy, bcopy, and a few other libc funtions, you gain most of
> the advantages of Solar Designer's patches. It also protects against a
> few things his patches don't --- such as simply installing a return
> address to some location not on the stack. (Yes, it doesn't protect
> against open-coded for loops that reference *cp++; the libc patch
> approach isn't perfect. But then again, neither is the non-executable
> stack hack.)

Exactly how do you propose to make that work? Will the unbounded
str*() and mem*() functions simply have an implicit limit on the
number of characters they copy, or make complex checks to
determine whether copy targets are on the stack and guess how to
bound them to avoid overwriting important parts of the stack
frame? How do you pick the implicit limit that prevents buffer
overruns in an effective number of cases?

I see a non-executable stack as being completely in line with all
the other security partitioning and protection methods that are
already in an operating system -- page protections and virtual
memory partitioning so programs can't access or modify memory
they aren't supposed to; permissions and user/group checks so
programs can't access or modify resources they're not supposed to
and users can't execute programs or modify files they're not
supposed to, and so on. Many of these things could also be
accomplished by careful coding in programs, but these protections
are put into the operating system because programs cannot be
universally trusted to play nice.

The classic stack buffer overrun (smash the stack with code to be
executed on the stack) is always going to be easier to construct
than trickier buffer overruns that try to return into locations
outside the stack, because the stack is mapped at a fixed easily
determined location in all programs, while the location of data
buffers and library routines vary greatly. And since it is
easier to construct, _and_ if systems continue to permit it, then
it will continue to be deployed.

Come to think of it, the ability to have non-executable data
pages would also be nice for high-security systems, since it
would defeat even the more sophisticated stack overflow attacks.

> So why aren't the folks who think that every marginal increase in
> security, is worth any arbitrary amount of extra code complexity (after
> all, *they're* not the ones who have to maintain it :-), lobbying the
> glibc maintainers to put such hacks into libc? Just a thought.....
>
> - Ted

My position is that on OSes and architectures that support it, a
non-executable stack provides a much more than marginal increase
in security for very little code complexity (as little as not
setting the execute bit on page permissions for stack pages, if
the architecture supports it).

I understand that the i386 architecture doesn't have page-level
execute permissions and that Solar Designer's patch goes through
some fairly complex gyrations to obtain a (mostly) non-executable
stack, so from an i386-centric point of view I can see how many
would think that it's too much code complexity for what it buys.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/