Re: Stopping buffer-overflow security exploits using page protect

From: Crispin Cowan (crispin@wirex.com)
Date: Sun Jul 30 2000 - 23:25:04 EST


Gary Funck wrote:

> On Jul 29, 12:49pm, Oliver Xymoron wrote:
> > The problem isn't Intel's fault or any OS's, it's a problem in the C
> > language and compiler. There are 5 fixes:
> >
> > a) write safe code (which has so far proved hard)
> > b) compile with bounds-checking (big performance hit)
>
> What is the level of performance hit, using bounds-checking?
>

Highly variable. The best example of a full bounds-checking C compiler
is the GCC enhancement here http://web.inter.nl.net/hcc/Haj.Ten.Brugge/

Based on the compiler's documentation, it imposes between 3X and 30X
slowdowns, depending on the application. One of my favorite benchmarks
for security overhead is SSH: It's a real network service that needs to
be secure, so one really cares about the performance overhead of
protecting SSH. Based on e-mail correspondence with Kurt Roeckx (one of
the developers) this bounds checking compiler imposes a 12X slowdown
(1200% overhead) on SSH throughput.

> > c) compile with StackGuard, etc. (doesn't stop exploits that corrupt
> > other locals)
>

We have also benchmarked StackGuard's overhead on SSH throughput here
http://immunix.org/StackGuard/performance.html Experimentation shows
that the StackGuard overhead on SSH throughput is below experimental
error.

With respect to the subject line, and Bruce's article: we did try using
MMU protection to implement StackGuard. The catch is that MMU
manipulation instructions are privileged, and so you have to issue a
system call to do it. The result is that you need to make two system
calls per function call. Experimentally, this imposes 8000% overhead.
So we dropped the approach in favor of StackGuard's current "canary"
defense.

> > d) separate the return address stack from the automatic variable
> stack
> > (ditto)
>

There is a project called "StackShiled" trying this approach
http://www.angelfire.com/sk/stackshield/
StackShield appears to offer:

   * comparable protection to StackGuard. I argue that StackGuard is
     safer, the StackShield guys argue that StackShield is safer. In
     either case, the differences are small.
   * comparable performance to StackGuard
   * significantly less practical than StackGuard: StackShield requires
     that a makefile be hacked so that the compile phase outputs
     assembler source, which is piped through StackShield, before it is
     ultimately assembled into a .o and linked. StackGuard is a
     transparent patch to gcc.
   * significantly less validation than StackGuard: StackGuarded
     systems have been in full production use for over two years, while
     StackShield calls itself "beta 0.7". Get your StackGuarded Linux
     systems here http://immunix.org/

> > e) use another language (performance)
>
> Might there also be an 'alternate universe' where the damage caused
> by exploit-induced loss of control could be reduced/limited?
>

There are also a variety of projects working on this approach. They can
generally be characterized as "sandbox" or "cage" techniques, in which a
process that you really need, but do not trust, is confined to some
subset of the machine's resources. The major distinguishing
characteristics are how to characterize a process to be confined, and
how to characterize its confinement. Here's an incomplete set of
projects:

   * chroot: standard feature in Linux (and most other) UNIX kernels.
     chroot changes the root of the file system to a designated
     subdirectory. This isolates the chrooted process (and its
     children) to that subdirectory, preventing corruption of other
     parts of the file system.
   * I chaired a session at USENIX Security 1999 (Washington DC) on
     "cages" that presented three papers:
     http://www.usenix.org/events/sec99/technical.html
   * Linux Privs/Capabilities: privs lets you specify that a program
     has one of 32 "capabilities" so that you can grant special powers
     at a granularity finer than "all of root's power". Processes to be
     confined are identified by status bits in the file system on the
     executable file (like suid) and confinement is statically
     determined by the kernel implementation.
   * Janus http://www.cs.berkeley.edu/~daw/janus/ : confines "helper
     apps" to a secure environment. Janus is a user-land mediator, not
     a kernel mod. The result of that design decision is:
        o slowdown: each syscall the confined process makes results in
          four user-kernel transitions.
        o Solaris-specific: Janus depends on a Solaris-specific feature
          to be able to capture and mediate all of the syscalls that
          another process is making.
   * SubDomain http://immunix.org/subdomain.html : Another of my
     team's projects. SubDomain is a Linux kernel enhancement that lets
     the sys admin specify a set of programs by name to be confined.
     Each confined program gets access only to the named files, with the
     specified access modes (RWX). SubDomain is kinda like a flexible
     chroot on steroids. The difference is that while chroot completely
     isolates the jailed program, SubDomain gives the jailed program
     controlled access to the designated parts of the file system. Thus
     I have characterized the difference between chroot and SubDomain as
     "chroot is confinement by value", while "SubDomain is confinement
     by reference". I will be presenting a SubDomain paper to USENIX
     LISA in December http://www.usenix.org/events/lisa2000/

Crispin

--
Crispin Cowan, Chief Scientist, WireX Communications, Inc. http://wirex.com
Free Hardened Linux Distribution:                          http://immunix.org

- 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/



This archive was generated by hypermail 2b29 : Mon Jul 31 2000 - 21:00:32 EST