LWN.net Logo

"Exec Shield" for Linux

Ingo Molnar has announced the availability of a patch (for the 2.4.21 release candidate kernel) called "Exec Shield." It uses some new techniques to prevent the injection of executable via buffer overrun and related attacks. The patch looks like it could protect against a wide variety of exploits. It's not clear how far this patch will get in the development series, since Linus has been hostile to this type of patch in the past. Marcelo could prove more accommodating in 2.4, and, of course, vendors can always apply the patch themselves even if it does not go into the mainline kernel.
(Log in to post comments)

"Exec Shield" for Linux

Posted May 2, 2003 21:06 UTC (Fri) by welinder (guest, #4699) [Link]

And in the process, you probably kill

  • wine, which needs to link some DLLs at certain addresses
  • gdb, which needs (needed?) to put some code into the child when using "print" for calling functions in the child.
  • ...
There are better ways, IMHO. For example the modified gccs out there that protect the return address with canaries.

"Exec Shield" for Linux

Posted May 2, 2003 21:14 UTC (Fri) by john54 (guest, #10988) [Link]

As far as I can see, it should not be a problem, as long as Wine creates those DLL areas as PROT_EXEC - which it probably already does. Alot of other code would break if that were not possible - such as the Linux dynamic linker.

"Exec Shield" for Linux

Posted May 3, 2003 4:24 UTC (Sat) by Gabe (guest, #10514) [Link]

Does it matter if talking about servers? Desktop security takes a back seat to server security.

"Exec Shield" for Linux

Posted May 3, 2003 6:26 UTC (Sat) by ctg (subscriber, #3459) [Link]

Think "application server". You might be running Windows applications on
your server and distribute them via X to user's screens. Now if you were
in a school/college/fairly hostile environment, then you might be
interested in this sort of security.

"Exec Shield" for Linux

Posted May 2, 2003 21:16 UTC (Fri) by leonb (guest, #3054) [Link]

I think that the g++ virtual function dispatched
for classes with multiple inheritance works
by constructing executable thunks in the stack.
Making the stack non executable
would break this.

- L.

"Exec Shield" for Linux

Posted May 2, 2003 22:29 UTC (Fri) by JoeBuck (subscriber, #2330) [Link]

No, this is incorrect; the thunks that GNU C++ uses for multiple inheritance are not on the stack. They are in the program text section just like all other code. (The thunk basically just adjusts the value of the this pointer and then jumps to the entry point of the virtual function).

For nested functions, a GCC extension, a "trampoline" function is built that lives on the stack, so a non-executable stack patch will break this. But standard C and C++ codes should not be affected.

"Exec Shield" for Linux

Posted May 3, 2003 22:29 UTC (Sat) by dvdeug (subscriber, #10998) [Link]

For nested functions, a GCC extension, a "trampoline" function is built that lives on the stack, so a non-executable stack patch will break this. But standard C and C++ codes should not be affected

Standard C and C++ codes shouldn't be affected, but other languages like Ada make heavy use of nested functions.

"Exec Shield" for Linux

Posted May 5, 2003 2:29 UTC (Mon) by jamesh (subscriber, #1159) [Link]

Are you sure that Ada would be affected? The "trampoline" function that is produced by the C and C++ compilers sounds like something necessary to implement nested functions while maintaining the same ABI and calling conventions. The fact that the implementation of this C extension breaks doesn't imply that Ada will break.

Of course, the best way to be sure is to download and apply the kernel patch and see what happens. I am sure that Ingo would be interested in the results.

"Exec Shield" for Linux: Linus is right

Posted May 2, 2003 22:51 UTC (Fri) by JoeBuck (subscriber, #2330) [Link]

Since Linus has been so kind as to give everyone an easy-to-follow recipe (and I just checked to be sure that current glibc's have a "/bin/sh" string, they do), it seems that if a vendor wants to get any extra security by using this patch, the vendor will also need to purge all common shared libraries of any strings of that form. Unfortunately, it gets worse: assuming that /bin is on the path, all the bad guy needs is the three characters 's', 'h', and NUL, to appear in sequence somewhere in the binary or in some shared library to use the Torvalds attack, something that is a virtual certainty to occur just by chance.

Now, it is true that the existing script kiddie exploits would break, but in about a month, we'd have a whole new set. So I've got to agree with Linus here.

"Exec Shield" for Linux: Linus is right

Posted May 3, 2003 7:50 UTC (Sat) by john54 (guest, #10988) [Link]

You are wrong. Lets take the big sendmail hole as an example, in which case a carefully constructed email header overflows a string buffer and a jump address located after the buffer. In the sendmail hole case, Linus' method works around any non-executable stack patch, but it does not work with the exec shield patch applied.

With the exec shield activated, as you can see in the original article, the system() function (part of libc) is placed into the "ASCII armor" area. So by overflowing the return address (or a function pointer, or anything else) with an _ASCII_ email header you simply cannot generate the proper return address that jumps on the system() function, because the address of the system() function contains the \0 [zero] byte. You can jump to any other address in virtual memory but the ASCII armor - exactly there are all the important shared libraries.

Even if 'by chance' there would be a lucky combination of bytes somewhere in virtual memory that could be used to get a shell, the exec shield does not allow those addresses to be executed.

So it's not just a matter of putting shared libraries into the ASCII-armor, but it's also the matter of restricting execution to _only_ this area. This is that makes this method so effective.

If the overflow is not ASCII-based, then it can be exploited in theory, as stated in the article as well. (most of the recent 'big' buffer-overflow holes were ASCII-based) But one thing is clear, the exec shield is much more than just a non-executable stack patch.

"Exec Shield" for Linux: Linus is right

Posted May 4, 2003 22:19 UTC (Sun) by JoeBuck (subscriber, #2330) [Link]

There have been bugs in image decoding libraries (PNG, JPEG) in which deliberately corrupt data causes a buffer overflow. In this case, the overflow data may contain NUL characters, so the ASCII armor trick will not work. You're also forgetting about locales that specify non-8-bit character sets.

However, you are correct that tactics that just provide a long ASCII string to cause the overflow will not work.

"Exec Shield" for Linux

Posted May 3, 2003 1:51 UTC (Sat) by DaveK (subscriber, #2531) [Link]

Marcelo could prove more accommodating in 2.4,

But sometime within the next six months - before 2.4.21 surfaces - numerous methods of getting around it will have surfaced

"Exec Shield" for Linux

Posted May 4, 2003 8:54 UTC (Sun) by Peter (guest, #1127) [Link]

Does anyone know if this patch is compatible with prelink? By "compatible" I mean that prelink is not rendered pointless?

It seems that prelink would not work, even if it were aware of the requirement to put library addresses in the ascii armor area. My system has about 79 MB of shared libraries (find /lib /usr/lib -type f -name \*.so\* | xargs size | awk '{n+=$1}END{print n}') - only a fraction will fit in 15 MB, obviously, so prelink would have to do some major overlapping of unrelated libs. And that's without major hogs like GNOME 2 or KDE 3.

Oh well, prelinking (like -O3 -mpentium4) is only of marginal benefit in most production environments.

mmap(0,...) placement options

Posted May 6, 2003 14:48 UTC (Tue) by jreiser (subscriber, #11027) [Link]

A related idea is giving the user more control over mmap(0,...) in general. Make TASK_UNMAPPED_BASE an inherited part of process state, and control it with setrlimit()/getrlimit(). With .task_unmapped_base set to 1MB, then in Ingo's "cat" example even the locale pages would reside in ASCII Armor. The cost is 4 bytes of process state, plus a few lines in setrlimit/getrlimit.

Kasper Dupont has developed patches to support this. See here.

Also, the builders of applications can arrange for "ASCII Armor" placement of mmap(0,...) even in systems without kernel patches. See my project tub.

Further, if the kernel provided a binary structure interface to /proc/self/maps then it would be much easier and more reliable for users to do these things by themselves. Win32 has an interface VirtualQuery() which provides for introspective examination of the address space mappings.

Copyright © 2003, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds