linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-05  7:14 Ingo Molnar
  0 siblings, 0 replies; 48+ messages in thread
From: Ingo Molnar @ 2003-05-05  7:14 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andi Kleen


On 4 May 2003, Andi Kleen wrote:

> Ingo Molnar <mingo@redhat.com> writes:
> 
> > ie. if the binary anywhere has code that does:
> > 
> > 	system("/bin/sh")
> 
> You just need system(char *arg) { ... } (= in every libc). Then put
> /bin/sh somewhere and a pointer to it on the stack as argument and
> overwrite some return address on the stack to jump to it.

well, how do you put the pointer on the stack if your only way to get into
the ASCII-area is to stop the overflow early and use the final \0 ? [and
the parameter has to be put _after_ the enclosing \0. ] It's not 100%
impossible, but in the common case looks quite unlikely.

	Ingo


^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-04 23:55 Chuck Ebbert
  2003-05-05  3:14 ` H. Peter Anvin
  0 siblings, 1 reply; 48+ messages in thread
From: Chuck Ebbert @ 2003-05-04 23:55 UTC (permalink / raw)
  To: H. Peter Anvin; +Cc: linux-kernel

> There is another issue: x86 uses relative jumps, so although "ASCII
> armor" addresses aren't easily accessible using return address smashes
> (although the \0 at the end thing is a real issue), you may be able to
> get to them through a jump instruction.

 Does the instruction-pointer-relative data addressing mode added by
AMD64 make these exploits easier?  Maybe someone should be working on a
version of this patch for that platform...



^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-04 16:20 Yoav Weiss
  0 siblings, 0 replies; 48+ messages in thread
From: Yoav Weiss @ 2003-05-04 16:20 UTC (permalink / raw)
  To: Chuck Ebbert; +Cc: linux-kernel

>   I looked at sys_iopl() and it seems to be checking if its param is
> > 3, so EBX on the stack must be 0x00000003 to set iopl to 3.

You're partially right.
I did miss the 'if (level > 3)' test because I was looking at Ingo's patch
rather than the whole function.
However, it doesn't have to be 3 because we don't really need to set iopl
to anything.  As long as (level > old) is true, which, at this point would
be any param between 1 and 3, current->mm->context.exec_limit = 0xffffffff
will be executed.  The attack won't rely on iopl level itself.  It just
uses iopl to set exec_limit to 0xffffffff so further shellcode can be
called.  In order to exploit this, one would have to find an override
condition where EBX happens to be between 1 and 3.  Tricky, but not as
hard as finding a condition where it points to a "/bin/sh" string :)
And once such call to iopl has been made, any standard shellcode can be
executed from anywhere in memory.

Anyway, as Ingo already said, this whole piece of code is going away on
the next version so we're off-topic now.


>   Shouldnt it be like this?
>

Probably yes, but again - its not related to the potential hole I
described.  I don't know why its defined like that, but maybe the
maintainer of iopl can enlighten us on that.

	Yoav Weiss


^ permalink raw reply	[flat|nested] 48+ messages in thread
[parent not found: <Pine.LNX.4.44.0305040404300.12757-100000@devserv.devel.redhat.com.suse.lists.linux.kernel>]
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-04 14:25 Chuck Ebbert
  2003-05-04 22:22 ` Richard Henderson
  0 siblings, 1 reply; 48+ messages in thread
From: Chuck Ebbert @ 2003-05-04 14:25 UTC (permalink / raw)
  To: Yoav Weiss; +Cc: linux-kernel

> btw, I guess that now, at least when X_workaround==1, exploits will focus
> on getting iopl(2) called before they get the actual shellcode called.
> In some cases it may be easy to cause a call to iopl (param doesn't matter
> as long as its not zero).

  I looked at sys_iopl() and it seems to be checking if its param is
> 3, so EBX on the stack must be 0x00000003 to set iopl to 3.

  The declaration is misleading ("unused"???:)

asmlinkage int sys_iopl(unsigned long unused)
{
        struct pt_regs * regs = (struct pt_regs *) &unused;       <== yuck!
        unsigned int level = regs->ebx;
        ...
        if (level > 3)
                return -EINVAL;


  Shouldnt it be like this?

asmlinkage int sys_iopl (struct pt_regs regs)
{
        unsigned int level = regs.ebx;
        ...


fork, clone, vfork and execve all declare it that way...




^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-04 11:19 Yoav Weiss
  2003-05-04 13:51 ` Ingo Molnar
  0 siblings, 1 reply; 48+ messages in thread
From: Yoav Weiss @ 2003-05-04 11:19 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel

On Fri, 2 May 2003, Ingo Molnar wrote:

> Furthermore, the kernel also remaps all PROT_EXEC mappings to the
> so-called ASCII-armor area, which on x86 is the addresses 0-16MB.

I don't see how the case of mprotect(HIGH_ADDRESS, LEN, PROT_EXEC) be
handled.  Unlike mremap, mprotect doesn't offer a way to inform the user
about a change of address.

If I understand correctly, such case will cause a call to
arch_add_exec_range(current->mm, vma) without any remapping, thus breaking
the protection.

One case where this would happen is some of the ancient loaders.  IIRC,
libc4's loader did just that.  (right, nobody uses it anymore :)

btw, I guess that now, at least when X_workaround==1, exploits will focus
on getting iopl(2) called before they get the actual shellcode called.
In some cases it may be easy to cause a call to iopl (param doesn't matter
as long as its not zero).  Once this is achieved, protection is disabled.

For that reason, maybe X_workaround should be controlled per-executable
by another ELF flag and not as a system-wide property.

	Yoav Weiss

--
Please CC me on any reply.


^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-03 13:19 linux
  2003-05-03 23:00 ` Valdis.Kletnieks
  0 siblings, 1 reply; 48+ messages in thread
From: linux @ 2003-05-03 13:19 UTC (permalink / raw)
  To: linux-kernel

> Ingo Molnar wrote:
> On Fri, 2 May 2003, Carl-Daniel Hailfinger wrote:
>> If my math is correct,
>> 0x01000000 is 16 MB boundary
>> 0x01003fff is outside the ASCII-armor.
> 
> the ASCII-armor, more precisely, is between addresses 0x00000000 and
> 0x0100ffff. Ie. 16 MB + 64K. [in the remaining 64K the \0 character is in
> the second byte of the address.] So the 0x01003fff address is still inside 
> the ASCII-armor.

To be precise, the first addressible address is 0x01010101 (16M+64K+256+1).
Rounding this to a page boundary produces the figure above.

Just as a reminder, the standard stack-smashing attack for non-executable
stacks works by overwriting the current call frame's return address with

[entry address of interesting function, like system()]
[dummy return address]
[char *argument]
[string pointed to by above argument]

When the current function returns, the CPU will return to the entry
address of system() with the desired arguments on the stack.
(This is trickier on architectures which put arguments in registers,
so you have to find a "pop argument registers; return" sequence in the
standard library and return to that first.)

The ASCII string is then passed to some "interesting" function which
has interpreter powers and "executes" it without caring about the
processor's idea of execute permission.

If this is done by passing an unexpectedly long input to strcpy()
or gets(), then none of the arguments can have an embedded zero byte,
except the final string.

The stack address is needed to arrange for the char *argument to point
to the string.  If the string is an executable path, some uncertainty
can be resolved by using a path like:

/../../../../../../../../../../../../../../../../../bin/sh

Or, if you know the stack is 2-byte aligned (people aren't usually
willing to put up with the performance hit for odd stack pointers even
on architectures like x86 which can handle them), you can use

/./././././././././././././././././././././././././bin/sh

A pointer a little past the start of the string will still
end up referencing /bin/sh.



An interesting question arises: is the number of useful interpreter
functions (system, popen, exec*) sufficiently low that they could be
removed from libc.so entirely and only staticly linked, so processes
that didn't use them wouldn't even have them in their address space,
and ones that did would have them at less predictible addresses?

Right now, I'm thinking only of functions that end up calling execve();
are there any other sufficiently powerful interpreters hiding in common
system libraries?  regexec()?

^ permalink raw reply	[flat|nested] 48+ messages in thread
* Re: [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-02 22:46 Chuck Ebbert
  0 siblings, 0 replies; 48+ messages in thread
From: Chuck Ebbert @ 2003-05-02 22:46 UTC (permalink / raw)
  To: John Bradford; +Cc: linux-kernel

John Bradford wrote:

> Slightly off-topic, but does anybody know whether IA64 or x86-64 allow
> you to make the stack non-executable in the same way you can on SPARC?

 IA64 supports a mind-boggling variety of page-level protection modes,
including execute-only pages that usermode can jump to and get
'promoted' to lower (more privileged) levels.  _And_ it supports
protection keys that can be attached to pages so your process needs
to have the key loaded into a register to touch those pages.  The keys
can themselves be marked read/write/execute disable on loading, so
the supervisor can give you a key that keeps you from executing pages
even if their page-level protections would otherwise allow it.

 AMD64 supports a simple NX (no execute) bit that keeps both supervisor
and user code from executing, and that's probably all anyone really needs.

------
 Chuck

^ permalink raw reply	[flat|nested] 48+ messages in thread
* [Announcement] "Exec Shield", new Linux security feature
@ 2003-05-02 16:37 Ingo Molnar
  2003-05-02 17:05 ` Matthias Andree
                   ` (3 more replies)
  0 siblings, 4 replies; 48+ messages in thread
From: Ingo Molnar @ 2003-05-02 16:37 UTC (permalink / raw)
  To: linux-kernel


We are pleased to announce the first publically available source code
release of a new kernel-based security feature called the "Exec Shield",
for Linux/x86. The kernel patch (against 2.4.21-rc1, released under the
GPL/OSL) can be downloaded from:

	http://redhat.com/~mingo/exec-shield/

The exec-shield feature provides protection against stack, buffer or
function pointer overflows, and against other types of exploits that rely
on overwriting data structures and/or putting code into those structures.
The patch also makes it harder to pass in and execute the so-called
'shell-code' of exploits. The patch works transparently, ie. no
application recompilation is necessary.

Background:
-----------

It is commonly known that x86 pagetables do not support the so-called
executable bit in the pagetable entries - PROT_EXEC and PROT_READ are
merged into a single 'read or execute' flag. This means that even if an
application marks a certain memory area non-executable (by not providing
the PROT_EXEC flag upon mapping it) under x86, that area is still
executable, if the area is PROT_READ.

Furthermore, the x86 ELF ABI marks the process stack executable, which
requires that the stack is marked executable even on CPUs that support an
executable bit in the pagetables.

This problem has been addressed in the past by various kernel patches,
such as Solar Designer's excellent "non-exec stack patch". These patches
mostly operate by using the x86 segmentation feature to set the code
segment 'limit' value to a certain fixed value that points right below the
stack frame. The exec-shield tries to cover as much virtual memory via the
code segment limit as possible - not just the stack.

Implementation:
---------------

The exec-shield feature works via the kernel transparently tracking
executable mappings an application specifies, and maintains a 'maximum
executable address' value. This is called the 'exec-limit'. The scheduler
uses the exec-limit to update the code segment descriptor upon each
context-switch. Since each process (or thread) in the system can have a
different exec-limit, the scheduler sets the user code segment dynamically
so that always the correct code-segment limit is used.

the kernel caches the user segment descriptor value, so the overhead in
the context-switch path is a very cheap, unconditional 6-byte write to the
GDT, costing 2-3 cycles at most.

Furthermore, the kernel also remaps all PROT_EXEC mappings to the
so-called ASCII-armor area, which on x86 is the addresses 0-16MB. These
addresses are special because they cannot be jumped to via ASCII-based
overflows. E.g. if a buggy application can be overflown via a long URL:

  http://somehost/buggy.app?realyloooooooooooooooooooong.123489719875

then only ASCII (ie. value 1-255) characters can be used by attackers. If
all executable addresses are in the ASCII-armor, then no attack URL can be
used to jump into the executable code - ie. the attack cannot be
successful. (because no URL string can contain the \0 character.) E.g. the
recent sendmail remote root attack was an ASCII-based overflow as well.

With the exec-shield activated, and the 'cat' binary relinked into the the
ASCII-armor, the following layout is created:

  $ ./cat-lowaddr /proc/self/maps
  00101000-00116000 r-xp 00000000 03:01 319365     /lib/ld-2.3.2.so
  00116000-00117000 rw-p 00014000 03:01 319365     /lib/ld-2.3.2.so
  00117000-0024a000 r-xp 00000000 03:01 319439     /lib/libc-2.3.2.so
  0024a000-0024e000 rw-p 00132000 03:01 319439     /lib/libc-2.3.2.so
  0024e000-00250000 rw-p 00000000 00:00 0
  01000000-01004000 r-xp 00000000 16:01 2036120    /home/mingo/cat-lowaddr
  01004000-01005000 rw-p 00003000 16:01 2036120    /home/mingo/cat-lowaddr
  01005000-01006000 rw-p 00000000 00:00 0
  40000000-40001000 rw-p 00000000 00:00 0
  40001000-40201000 r--p 00000000 03:01 464809     locale-archive
  40201000-40207000 r--p 00915000 03:01 464809     locale-archive
  40207000-40234000 r--p 0091f000 03:01 464809     locale-archive
  40234000-40235000 r--p 00955000 03:01 464809     locale-archive
  bfffe000-c0000000 rw-p fffff000 00:00 0

In the above layout, the highest executable address is 0x01003fff, ie.
every executable address is in the ASCII-armor.

this means that not only the stack is non-executable, but lots of
mmap()-ed data areas and the malloc() heap is non-executable as well.  
(some data areas are still executable, but most of them are not.)

the first 1MB of the ASCII-armor is left unused to provide NULL pointer
dereference protection and leave space for 16-bit emulation mappings used
by XFree86 and others.

Compare this with the memory layout without exec-shield:

  08048000-0804b000 r-xp 00000000 16:01 3367       /bin/cat
  0804b000-0804c000 rw-p 00003000 16:01 3367       /bin/cat
  0804c000-0804e000 rwxp 00000000 00:00 0
  40000000-40012000 r-xp 00000000 16:01 3759       /lib/ld-2.2.5.so
  40012000-40013000 rw-p 00011000 16:01 3759       /lib/ld-2.2.5.so
  40013000-40014000 rw-p 00000000 00:00 0
  40018000-40129000 r-xp 00000000 16:01 4058       /lib/libc-2.2.5.so
  40129000-4012f000 rw-p 00111000 16:01 4058       /lib/libc-2.2.5.so
  4012f000-40133000 rw-p 00000000 00:00 0
  bffff000-c0000000 rwxp 00000000 00:00 0

In this layout none of the executable areas are in the ASCII-armor, plus
the exec-limit is 0xbfffffff (3GB) - ie. including all userspace mappings.

Note that the kernel will relocate every shared-library to the
ASCII-armor, but the binary address is determined at link-time. To ease
the relinking of applications to the ASCII-armor, Arjan Van de Ven has
written a binutils patch (binutils-2.13.90.0.18-elf-small.patch), which
adds a new 'ld' flag "ld -melf_i386_small" (or "gcc -Wl,-melf_i386_small")
to relink applications into the ASCII-armor. (The patch can be found at
the exec-shield URL as well.)

Overhead:
---------

the patch was designed to be as efficient as possible. There's a very
minimal (couple of cycles) tracking overhead for every PROT_MMAP
system-call, plus there's the 2-3 cycles cost per context-switch.

Limitations:
------------

This feature will not protect against every type of attack.

E.g. if an overflow can be used to overwrite a local variable which
changes the flow of control in a way that compromises the system. But we
do believe that this feature will stop every attack that is purely
operating by overflowing the return address on the stack, or overflowing a
function pointer in the heap. Furthermore, exec-shield makes it quite hard
to mount a successful attack even in the other cases, because it inhibits
the execution of exploit shell-code, in most cases.

also, if the overflow is within the exec-shield itself (e.g. within the
data section of one of the shared library objects in the ASCII-armor) then
the overflow might be possible to exploit.

All in one, exec-shield is one barrier against attacks, not blanket 100%
protection in any way. The most efficient security can be provided by
installing as many layers as possible.

To provide as good protection as possible, there's no trampoline
workaround in the exec-shield code - ie. exec-limit violations in the
trampoline case are never let through. Applications that need to rely on
gcc trampolines will have to use the per-binary ELF flag to make the stack
executable again. (The ELF flag is the same as used by Solar Designer's
non-exec stack patch, to provide as much compatibility with existing
non-exec-stack installations as possible.)

The exec-shield feature will uncover applications that incorrectly assumed
that PROT_READ allows execution on x86. One such example is the XFree86
module loader. The latest XFree86 on rawhide.redhat.com fixes this
problem. For those who cannot install the XFree86 bugfix at the moment
there's a workaround added by the patch, which can be activated via:

    echo 1 > /proc/sys/kernel/X-workaround

This will make every iopl() using application (such as X) have the
exec-shield disabled. Other applications (sendmail, etc.) will still have
the exec-shield enabled. This workaround is default-off. We strongly
encourage to solve this problem by upgrading X, or by using the 'chkstk'
utility to make X's stack forced-executable.

Using it:
---------

Apply the exec-shield-2.4.21-rc1-B6 kernel patch to the 2.4.21-rc1 kernel,
recompile & install the kernel and reboot into it, that's all.

There is a new boot-time kernel command line option called exec-shield=,
which has 4 values. Each value represents a different level of security:

 exec-shield=0    - always-disabled
 exec-shield=1    - default disabled, except binaries that enable it
 exec-shield=2    - default enabled, except binaries that disable it
 exec-shield=3    - always-enabled

the current patch defaults to 'exec-shield=2'. The security level can also
be changed runtime, by writing the level into /proc:

  echo 0 > /proc/sys/kernel/exec-shield

IMPORTANT: security-relevant applications that were started while the
exec-shield was disabled, will have an executable stack and will thus have
to be restarted if the exec-shield is enabled again.

I've also uploaded a modified version of Solar Designer's chstk.c code,
which adds the options necessary to change the 'enable non-exec stack' ELF
flag:

  $ ./chstk
  Usage: ./chstk OPTION FILE...
  Manage stack area executability flag for binaries

    -e    enable execution permission
    -E    enable non-execution permission
    -d    disable execution permission
    -D    disable non-execution permission
    -v    view current flag state

ie. there are two distinct flags, one for forcing an executable stack, one
for forcing a non-executable stack. If both flags are zero then the binary
will follow the system default.

ie. it's possible to use an exec-shield level of 1, and enable the
non-exec stack on a per binary basis, by using the 'exec-shield=1' boot
option and changing binaries one at a time:

   ./chstk -E /usr/sbin/sendmail

(People migrating production environments to an exec-shield kernel might
prefer this variant.)

anyway, comments, suggestions and test feedback is welcome.

	Ingo





^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2003-05-05 13:23 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <Pine.LNX.4.44.0305021325130.6565-100000@devserv.devel.redhat.com.suse.lists.linux.kernel>
     [not found] ` <200305021829.h42ITclA000178@81-2-122-30.bradfords.org.uk.suse.lists.linux.kernel>
     [not found]   ` <b8udjm$cgq$1@cesium.transmeta.com.suse.lists.linux.kernel>
2003-05-02 20:51     ` [Announcement] "Exec Shield", new Linux security feature Andi Kleen
2003-05-02 20:56       ` H. Peter Anvin
2003-05-02 21:07         ` Andi Kleen
2003-05-02 21:09           ` H. Peter Anvin
2003-05-02 21:25             ` Andi Kleen
2003-05-05  7:14 Ingo Molnar
  -- strict thread matches above, loose matches on Subject: below --
2003-05-04 23:55 Chuck Ebbert
2003-05-05  3:14 ` H. Peter Anvin
2003-05-04 16:20 Yoav Weiss
     [not found] <Pine.LNX.4.44.0305040404300.12757-100000@devserv.devel.redhat.com.suse.lists.linux.kernel>
     [not found] ` <Pine.LNX.4.44.0305040448250.24497-100000@devserv.devel.redhat.com.suse.lists.linux.kernel>
2003-05-04 15:48   ` Andi Kleen
2003-05-04 14:25 Chuck Ebbert
2003-05-04 22:22 ` Richard Henderson
2003-05-05  0:41   ` H. Peter Anvin
2003-05-04 11:19 Yoav Weiss
2003-05-04 13:51 ` Ingo Molnar
2003-05-03 13:19 linux
2003-05-03 23:00 ` Valdis.Kletnieks
2003-05-04  7:03   ` Calin A. Culianu
2003-05-04  8:49     ` Arjan van de Ven
2003-05-05 13:35     ` Jesse Pollard
2003-05-04 15:24   ` linux
2003-05-02 22:46 Chuck Ebbert
2003-05-02 16:37 Ingo Molnar
2003-05-02 17:05 ` Matthias Andree
2003-05-02 17:12   ` Marc-Christian Petersen
2003-05-02 17:12 ` Davide Libenzi
2003-05-02 17:18   ` Arjan van de Ven
2003-05-02 17:32     ` Ingo Molnar
2003-05-02 18:29       ` John Bradford
2003-05-02 18:32         ` H. Peter Anvin
2003-05-02 19:09         ` David Mosberger
2003-05-02 18:51       ` Davide Libenzi
     [not found]   ` <20030502172011$0947@gated-at.bofh.it>
2003-05-02 18:17     ` Florian Weimer
2003-05-02 18:29       ` Davide Libenzi
2003-05-02 18:32         ` Florian Weimer
2003-05-02 18:50           ` Davide Libenzi
2003-05-02 21:48 ` Carl-Daniel Hailfinger
2003-05-03  6:52   ` Ingo Molnar
2003-05-03  9:56     ` Carl-Daniel Hailfinger
2003-05-03 12:48       ` Arjan van de Ven
2003-05-04  6:52     ` Calin A. Culianu
2003-05-04  8:10       ` Ingo Molnar
2003-05-04  8:52         ` Ingo Molnar
2003-05-04 15:40           ` Calin A. Culianu
2003-05-04 15:48             ` Sean Neakums
2003-05-04 15:23         ` Calin A. Culianu
2003-05-04 20:07       ` H. Peter Anvin
2003-05-04 20:57 ` Kasper Dupont

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).