2003-05-02 16:25:03

by Ingo Molnar

[permalink] [raw]
Subject: [Announcement] "Exec Shield", new Linux security feature


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





2003-05-02 16:53:07

by Matthias Andree

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, 02 May 2003, Ingo Molnar wrote:

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

Am I the only one under the impression that this looks as though this
had waited for OpenBSD 3.3 to say "Blbrrrrrrrrp! we're first to have
stack protection in the kernel and don't need to hack gcc." (Their W^X
isn't enabled on the i386 architecture, but is due (on i386) in 3.4.)

2003-05-02 17:19:58

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On 2 May 2003, Arjan van de Ven wrote:

> > Ingo, do you want protection against shell code injection ? Have the
> > kernel to assign random stack addresses to processes and they won't be
> > able to guess the stack pointer to place the jump. I use a very simple
> > trick in my code :
>
> stack randomisation is already present in the kernel, in the form of
> cacheline coloring for HT cpus...

we could make it even more prominent than just coloring, to introduce the
kind of variability that Davide's approach introduces. It has to be a
separate patch obviously. This would further reduce the chance that a
remote attack that has to guess the stack would succeed on a random box.

Ingo



2003-05-02 20:57:56

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Andi Kleen wrote:
>>
>>Why is that? And, in particular, why is it "too late to turn it back
>
> mprotect() didn't (and probably still does not) work when you change
> PROT_EXEC.
>

Kernel bug or CPU bug?

-hpa

2003-05-02 18:37:24

by Davide Libenzi

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, 2 May 2003, Florian Weimer wrote:

> Davide Libenzi <[email protected]> writes:
>
> > On Fri, 2 May 2003, Florian Weimer wrote:
> >
> >> Davide Libenzi <[email protected]> writes:
> >>
> >> > Ingo, do you want protection against shell code injection ? Have the
> >> > kernel to assign random stack addresses to processes and they won't be
> >> > able to guess the stack pointer to place the jump.
> >>
> >> If your software is broken enough to have buffer overflow bugs, it's
> >> not entirely unlikely that it leaks the stack address as well (IIRC,
> >> BIND 8 did).
> >
> > Leaking the stack address is not a problem in this case, since the next
> > run will be very->very->very likely different.
>
> Usually, you can't afford a fork() and execve() for each request you
> process. 8-(

You just do it once in your main() task and one for each thread. It's not
so bad. Only thing is a ( tunable ) waste of stack space.


> (In addition, GCC might optimize away those alloca() calls.)

Luckily enough it doesn't. I checked this a long time ago since I had the
same fear due the builtin_alloca.



- Davide

2003-05-02 18:13:13

by John Bradford

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

> > > Ingo, do you want protection against shell code injection ? Have the
> > > kernel to assign random stack addresses to processes and they won't be
> > > able to guess the stack pointer to place the jump. I use a very simple
> > > trick in my code :
> >
> > stack randomisation is already present in the kernel, in the form of
> > cacheline coloring for HT cpus...
>
> we could make it even more prominent than just coloring, to introduce the
> kind of variability that Davide's approach introduces. It has to be a
> separate patch obviously. This would further reduce the chance that a
> remote attack that has to guess the stack would succeed on a random box.

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?

John.

2003-05-02 21:36:17

by Carl-Daniel Hailfinger

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

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. These
[snipped]
> In the above layout, the highest executable address is 0x01003fff, ie.
> every executable address is in the ASCII-armor.

If my math is correct,
0x01000000 is 16 MB boundary
0x01003fff is outside the ASCII-armor.

Another question:
Last time I checked, there were some problems with binary only drivers
(to name one, NVidia graphics) and a non-executable stack. Has this been
resolved?

Regards,
Carl-Daniel
--
http://www.hailfinger.org/

2003-05-02 21:12:41

by Andi Kleen

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, May 02, 2003 at 02:09:54PM -0700, H. Peter Anvin wrote:
> Andi Kleen wrote:
> >>
> >>Why is that? And, in particular, why is it "too late to turn it back
> >
> > mprotect() didn't (and probably still does not) work when you change
> > PROT_EXEC.
> >
>
> Kernel bug or CPU bug?

Kernel bug probably. Need to debug it sometime, but there were more important
things to do. Of course patches would be welcome if anybody is motivated ;)

-Andi

2003-05-02 18:57:12

by David Mosberger

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

>>>>> On Fri, 2 May 2003 19:29:38 +0100 (BST), John Bradford <[email protected]> said:

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

Not only "allow", but it's the default on ia64 linux.

--david

2003-05-02 18:38:53

by Davide Libenzi

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, 2 May 2003, Ingo Molnar wrote:

> > > Ingo, do you want protection against shell code injection ? Have the
> > > kernel to assign random stack addresses to processes and they won't be
> > > able to guess the stack pointer to place the jump. I use a very simple
> > > trick in my code :
> >
> > stack randomisation is already present in the kernel, in the form of
> > cacheline coloring for HT cpus...
>
> we could make it even more prominent than just coloring, to introduce the
> kind of variability that Davide's approach introduces. It has to be a
> separate patch obviously. This would further reduce the chance that a
> remote attack that has to guess the stack would succeed on a random box.

This definitely should take much code ;)



- Davide

2003-05-02 18:19:59

by Florian Weimer

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Davide Libenzi <[email protected]> writes:

> On Fri, 2 May 2003, Florian Weimer wrote:
>
>> Davide Libenzi <[email protected]> writes:
>>
>> > Ingo, do you want protection against shell code injection ? Have the
>> > kernel to assign random stack addresses to processes and they won't be
>> > able to guess the stack pointer to place the jump.
>>
>> If your software is broken enough to have buffer overflow bugs, it's
>> not entirely unlikely that it leaks the stack address as well (IIRC,
>> BIND 8 did).
>
> Leaking the stack address is not a problem in this case, since the next
> run will be very->very->very likely different.

Usually, you can't afford a fork() and execve() for each request you
process. 8-(

(In addition, GCC might optimize away those alloca() calls.)

2003-05-02 16:59:40

by Davide Libenzi

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, 2 May 2003, Ingo Molnar wrote:

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

[ very cool stuff ]

Ingo, do you want protection against shell code injection ? Have the
kernel to assign random stack addresses to processes and they won't be
able to guess the stack pointer to place the jump. I use a very simple
trick in my code :

#define MAX_STKSHIFT 1024

struct thrunner {
int (*proc)(void *);
void *data;
}

static int thread_runner(void *data) {
struct thrunner *thr = data;

alloca(myrand(MAX_STKSHIFT));
return thr->proc(thr->data);
}

int my_thread_create(int (*proc)(void *), void *data) {
struct thrunner *thr;
...
thr->proc = proc;
thr->data = data;
pthread_create(..., thread_runner, thr, ... );
...
}

int main(int argc, char *argv[]) {

mysrand();
...
}

Same thing can be done for non threaded programs :

int main(int argc, char *argv[]) {

mysrand();
alloca(myrand(MAX_STKSHIFT));
return real_main(argc, argv);
}


Yes, there's still the possibility that an attacker get lucky ( this get
lower increasing MAX_STKSHIFT ) and yes you waste some stack space. But,
oh well, it works w/out any kernel modification and it's portable on all
systems that have alloca().




- Davide

2003-05-02 18:05:02

by Florian Weimer

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Davide Libenzi <[email protected]> writes:

> Ingo, do you want protection against shell code injection ? Have the
> kernel to assign random stack addresses to processes and they won't be
> able to guess the stack pointer to place the jump.

If your software is broken enough to have buffer overflow bugs, it's
not entirely unlikely that it leaks the stack address as well (IIRC,
BIND 8 did).

2003-05-02 18:15:53

by Davide Libenzi

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Fri, 2 May 2003, Florian Weimer wrote:

> Davide Libenzi <[email protected]> writes:
>
> > Ingo, do you want protection against shell code injection ? Have the
> > kernel to assign random stack addresses to processes and they won't be
> > able to guess the stack pointer to place the jump.
>
> If your software is broken enough to have buffer overflow bugs, it's
> not entirely unlikely that it leaks the stack address as well (IIRC,
> BIND 8 did).

Leaking the stack address is not a problem in this case, since the next
run will be very->very->very likely different.



- Davide

2003-05-02 17:00:24

by Marc-Christian Petersen

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Friday 02 May 2003 19:05, Matthias Andree wrote:

Hi Matthias,

> Am I the only one under the impression that this looks as though this
> had waited for OpenBSD 3.3 to say "Blbrrrrrrrrp! we're first to have
> stack protection in the kernel and don't need to hack gcc." (Their W^X
> isn't enabled on the i386 architecture, but is due (on i386) in 3.4.)
hehehe ;) Well, they cannot say this even w/o exec shield b/c
http://www.grsecurity.net. :)

ciao, Marc


2003-05-02 17:06:01

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


> Ingo, do you want protection against shell code injection ? Have the
> kernel to assign random stack addresses to processes and they won't be
> able to guess the stack pointer to place the jump. I use a very simple
> trick in my code :

stack randomisation is already present in the kernel, in the form of
cacheline coloring for HT cpus...


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2003-05-02 22:35:26

by Chuck Ebbert

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

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

2003-05-03 06:39:57

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On Fri, 2 May 2003, Carl-Daniel Hailfinger wrote:

> 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. These
> [snipped]
> > In the above layout, the highest executable address is 0x01003fff, ie.
> > every executable address is in the ASCII-armor.
>
> 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.

> Another question: Last time I checked, there were some problems with
> binary only drivers (to name one, NVidia graphics) and a non-executable
> stack. Has this been resolved?

i'm not using any binary-only drivers, so i have no idea. But as long as
they use PROT_EXEC areas for code, they should be safe.

Ingo

2003-05-03 09:44:30

by Carl-Daniel Hailfinger

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Ingo Molnar wrote:
> On Fri, 2 May 2003, Carl-Daniel Hailfinger wrote:
>
>
>>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. These

What happens if the ASCII-armor area is full, i.e. sum(PROT_EXEC sizes)
>16MB for a given binary (Mozilla comes to mind)? Does loading fail or
does the binary run without any errors, giving the user a false sense of
security?

>>
>>[snipped]
>>
>>>In the above layout, the highest executable address is 0x01003fff, ie.
>>>every executable address is in the ASCII-armor.
>>
>>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.

Thanks. However, that brings me to the next question:

01000000-01004000 r-xp 00000000 16:01 2036120 /home/mingo/cat-lowaddr

I was wondering why the executable parts of the binary start at the 16
MB boundary. Is this always the case or just something that happens with
cat? In the first case, that would be bad for any binary with a
contiguous executable area bigger than 64K.

Thanks for answering,
Carl-Daniel

2003-05-03 12:36:17

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sat, 2003-05-03 at 11:56, Carl-Daniel Hailfinger wrote:
> Ingo Molnar wrote:
> > On Fri, 2 May 2003, Carl-Daniel Hailfinger wrote:
> >
> >
> >>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. These
>
> What happens if the ASCII-armor area is full, i.e. sum(PROT_EXEC sizes)
> >16MB for a given binary (Mozilla comes to mind)? Does loading fail or
> does the binary run without any errors, giving the user a false sense of
> security?

the binary will run without errors. And all the libs are still below the
main binary (the space for that is much bigger, like 128Mb) so the
executable limit is still the end of the main binary.
>
> > 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.
>
> Thanks. However, that brings me to the next question:
>
> 01000000-01004000 r-xp 00000000 16:01 2036120 /home/mingo/cat-lowaddr
>
> I was wondering why the executable parts of the binary start at the 16
> MB boundary. Is this always the case or just something that happens with
> cat? In the first case, that would be bad for any binary with a
> contiguous executable area bigger than 64K.

the start address of the binary is determined by ld at link time. This
cat binary was forced to go at exactly this address.
The patch to binutils in Ingo's directory will add the linker option to
move apps in this area; it will actually use a lower address than
01000000 to allow for bigger binaries. Obviously this 16Mb zone won't
fit all apps, but daemons like sendmail and sshd etc all just fit.


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2003-05-03 13:07:32

by George Spelvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

> 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()?

2003-05-03 22:48:10

by Valdis Klētnieks

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sat, 03 May 2003 13:19:52 -0000, [email protected] said:

> 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()?

This does absolutely nothing to stop an exploit from providing its own
inline version of execve(). There's nothing in libc that a process can't
do itself, inline.

A better bet is using an LSM module that prohibits exec() calls from any
unauthorized combinations of running program/user/etc.


Attachments:
(No filename) (226.00 B)

2003-05-04 06:39:55

by Calin A. Culianu

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


I don't really get it, but I could be a bit braindead now. I still don't
understand how the 0-16MB addresses are considered 'unjumpable' using the
ASCII string stack-smashing exploit.

IIRC, x86 ints have the high-order byte _last_ (ie the fourth byte).
What's to stop someone from, say, smashing a buffer (and consequently
return-address) on the stack using something like {0x01, 0x01, 0x01, 0x00}
which is really address '65793' in base-10. The above is a valid ASCII
string (3 1's followed by a NUL) which could conceivably end up on the
stack as the result of an errant strcpy() or gets() or whatever...

Clearly this address is less than 16MB, so then it must be possible to
jump to memory below 16MB.

Am I missing something??

-Calin

On Sat, 3 May 2003, Ingo Molnar wrote:

>
> On Fri, 2 May 2003, Carl-Daniel Hailfinger wrote:
>
> > 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. These
> > [snipped]
> > > In the above layout, the highest executable address is 0x01003fff, ie.
> > > every executable address is in the ASCII-armor.
> >
> > 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.
>
> > Another question: Last time I checked, there were some problems with
> > binary only drivers (to name one, NVidia graphics) and a non-executable
> > stack. Has this been resolved?
>
> i'm not using any binary-only drivers, so i have no idea. But as long as
> they use PROT_EXEC areas for code, they should be safe.
>
> Ingo
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>


2003-05-04 06:51:16

by Calin A. Culianu

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sat, 3 May 2003 [email protected] wrote:

> On Sat, 03 May 2003 13:19:52 -0000, [email protected] said:
>
> > 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()?
>
> This does absolutely nothing to stop an exploit from providing its own
> inline version of execve(). There's nothing in libc that a process can't
> do itself, inline.
>
> A better bet is using an LSM module that prohibits exec() calls from any
> unauthorized combinations of running program/user/etc.

Is that practical? I can see how with some daemons it would definitely be
useful to prohibit exec calls (maybe things like BIND don't need to exec
anything).. but some daemons do need to exec. An SMTPD may need to exec()
some helper processes (postfix for instance has a whole slew of helper
programs it uses).. and things like sshd need to exec a shell, etc..

It's still a good idea though, since some daemons don't need to exec,
ever. I guess this is one extra layer of protection. As Ingo said in his
announcement, the more layers of protection you have, the better.. and the
more difficult a cracker's job is.

-Calin

2003-05-04 07:57:43

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On Sun, 4 May 2003, Calin A. Culianu wrote:

> IIRC, x86 ints have the high-order byte _last_ (ie the fourth byte).
> What's to stop someone from, say, smashing a buffer (and consequently
> return-address) on the stack using something like {0x01, 0x01, 0x01,
> 0x00} which is really address '65793' in base-10. The above is a valid
> ASCII string (3 1's followed by a NUL) which could conceivably end up on
> the stack as the result of an errant strcpy() or gets() or whatever...

you are right, it is possible to use the enclosing \0 to generate an
address into the first 16MB, but how do you get any arguments passed to
that function?

Ingo

2003-05-04 08:36:58

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sun, 2003-05-04 at 09:03, Calin A. Culianu wrote:
> On Sat, 3 May 2003 [email protected] wrote:
>
> > On Sat, 03 May 2003 13:19:52 -0000, [email protected] said:
> >
> > > 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()?
> >
> > This does absolutely nothing to stop an exploit from providing its own
> > inline version of execve(). There's nothing in libc that a process can't
> > do itself, inline.
> >
> > A better bet is using an LSM module that prohibits exec() calls from any
> > unauthorized combinations of running program/user/etc.
>
> Is that practical? I can see how with some daemons it would definitely be
> useful to prohibit exec calls (maybe things like BIND don't need to exec
> anything).. but some daemons do need to exec. An SMTPD may need to exec()
> some helper processes (postfix for instance has a whole slew of helper
> programs it uses).. and things like sshd need to exec a shell, etc..
>
> It's still a good idea though, since some daemons don't need to exec,
> ever. I guess this is one extra layer of protection. As Ingo said in his
> announcement, the more layers of protection you have, the better.. and the
> more difficult a cracker's job is.

would be easier to make a CAP_EXEC capability that bind can drop then ;)


Attachments:
signature.asc (189.00 B)
This is a digitally signed message part

2003-05-04 08:40:23

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On Sun, 4 May 2003, Ingo Molnar wrote:

> > IIRC, x86 ints have the high-order byte _last_ (ie the fourth byte).
> > What's to stop someone from, say, smashing a buffer (and consequently
> > return-address) on the stack using something like {0x01, 0x01, 0x01,
> > 0x00} which is really address '65793' in base-10. The above is a valid
> > ASCII string (3 1's followed by a NUL) which could conceivably end up on
> > the stack as the result of an errant strcpy() or gets() or whatever...
>
> you are right, it is possible to use the enclosing \0 to generate an
> address into the first 16MB, but how do you get any arguments passed to
> that function?

ie. if the binary anywhere has code that does:

system("/bin/sh")

then this address can be jumped to and an exploit becomes possible. Also,
in the case of non-ASCII overflows the attacker has a much higher degree
of freedom to create a proper stackframe.

wrt. address-space randomization, "prelink -R" already provides quite good
randomization of the shared library addresses, which should give some
statistical protection against remote attacks, i dont think we'll need
kernel support for that.

Ingo

2003-05-04 11:06:51

by Yoav Weiss

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

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.

2003-05-04 13:39:30

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On Sun, 4 May 2003, Yoav Weiss wrote:

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

yes - the patch does not put any limit on which areas can be PROT_EXEC -
if the executable area is 'too wide' then there's no protection. The patch
tries to relocate areas which are freely relocatable, to make sure that in
the usual case the exec-limit will be quite low.

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

yeah, we should not be worried about old loaders.

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

i'll remove X_workaround from the next patch altogether - X can be fixed
by enabling an executable stack for the binary.

Ingo

2003-05-04 14:15:46

by Chuck Ebbert

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

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



2003-05-04 15:10:32

by Calin A. Culianu

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sun, 4 May 2003, Ingo Molnar wrote:

>
> On Sun, 4 May 2003, Calin A. Culianu wrote:
>
> > IIRC, x86 ints have the high-order byte _last_ (ie the fourth byte).
> > What's to stop someone from, say, smashing a buffer (and consequently
> > return-address) on the stack using something like {0x01, 0x01, 0x01,
> > 0x00} which is really address '65793' in base-10. The above is a valid
> > ASCII string (3 1's followed by a NUL) which could conceivably end up on
> > the stack as the result of an errant strcpy() or gets() or whatever...
>
> you are right, it is possible to use the enclosing \0 to generate an
> address into the first 16MB, but how do you get any arguments passed to
> that function?

Hehe you're right.. because of the trailing NUL it's impossible to get any
custom args passed to anything (like maybe libc.so's system() for
instance).

Yes, so this is a good layer of protection, because all the addresses
below 16MB guarantee this feature, at least...


2003-05-04 15:11:43

by George Spelvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sat, 03 May 2003 13:19:52 -0000, [email protected] said:
> 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()?

To which Valdis.Kletnieks replied:
> This does absolutely nothing to stop an exploit from providing its own
> inline version of execve(). There's nothing in libc that a process can't
> do itself, inline.

Ah, but with a non-executable stack, how do you arrange the inline code?
if you include it in the buffer overflow on the stack, it's in the
non-executable range.

You could arrange a return to memcpy(), with a stack like this:

[Address of memcpy()]
[Exploit target address (return address from memcpy)]
[Exploit target address (destination of memcpy)]
[Address of code on stack (source of memcpy)]
[Length of code on stack]
[Exploit code]

This would work if you had an "exploit target address" that was
writeable and executable, which this could copy the code to, but that's
hard to come by.

Now, we could stick a call to mprotect on the stack before that, but
it's hard to get the protection flags past the kernel test:

mm/mprotect.c, like 237:
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
return -EINVAL;

When your exploit can't include any null bytes.


Arjan's idea about a CAP_EXEC would be better, if it could be dropped
automagically by linker magic on existing code.

In fact, there are several other capabilities that would be nice to
have droppable:

- Ability to open an existing regular file or device (seekable,
persistent storage) for writing. An SMTP daemon could probably
drop this.
- Ability to create an externally accessible listening socket
(listen() on non-PF_UNIX)
- Ability to connect to an external address (connect() on non-PF_UNIX)

The PF_UNIX exception is for /dev/log.

2003-05-04 15:28:08

by Calin A. Culianu

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sun, 4 May 2003, Ingo Molnar wrote:

>
> On Sun, 4 May 2003, Ingo Molnar wrote:
>
> > > IIRC, x86 ints have the high-order byte _last_ (ie the fourth byte).
> > > What's to stop someone from, say, smashing a buffer (and consequently
> > > return-address) on the stack using something like {0x01, 0x01, 0x01,
> > > 0x00} which is really address '65793' in base-10. The above is a valid
> > > ASCII string (3 1's followed by a NUL) which could conceivably end up on
> > > the stack as the result of an errant strcpy() or gets() or whatever...
> >
> > you are right, it is possible to use the enclosing \0 to generate an
> > address into the first 16MB, but how do you get any arguments passed to
> > that function?
>
> ie. if the binary anywhere has code that does:
>
> system("/bin/sh")

Yes, certainly that would do it.. as would the situation if the binary is
written in such a way so that before breaking the buffer and setting up a
return into the <16MB address space, somehow you had enough control to set
up the stack frame so that it contains a pointer and the string "/bin/sh"
after the return address. Maybe by exploiting some local parameter
variable to the function you are in??

I don't know.. but at this point it gets really really unlikely that this
situation would exist, and you are right in saying that the more layers of
protection and the more improbable you make things for the cracker, the
better off you are.

Clearly without the ASCII-shield and exec-limit, it is pretty much
guaranteed that every unchecked buffer on the stack that accepts ASCII
data is crackable, whereas with the ASCII-shield + exec limit, the
guarantee still doesn't exist...

>
> wrt. address-space randomization, "prelink -R" already provides quite good
> randomization of the shared library addresses, which should give some
> statistical protection against remote attacks, i dont think we'll need
> kernel support for that.

What is prelink -R?

-Calin

2003-05-04 15:36:16

by Andi Kleen

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Ingo Molnar <[email protected]> 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.

-Andi

2003-05-04 15:35:41

by Sean Neakums

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

"Calin A. Culianu" <[email protected]> writes:

> On Sun, 4 May 2003, Ingo Molnar wrote:
>>
>> wrt. address-space randomization, "prelink -R" already provides quite good
>> randomization of the shared library addresses, which should give some
>> statistical protection against remote attacks, i dont think we'll need
>> kernel support for that.
>
> What is prelink -R?

-R --random
When assigning addresses to libraries, start with random
address within architecture dependant virtual address
space range. This can make some buffer overflow attacks
slightly harder to exploit, because libraries are not
present on the same addresses accross different
machines. Normally, assigning virtual addresses starts
at the bottom of architecture dependant range.

--
Sean Neakums - <[email protected]>

2003-05-04 16:08:09

by Yoav Weiss

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

> 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

2003-05-04 19:55:30

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Followup to: <[email protected]>
By author: "Calin A. Culianu" <[email protected]>
In newsgroup: linux.dev.kernel
>
> Clearly this address is less than 16MB, so then it must be possible to
> jump to memory below 16MB.
>

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.

-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
Architectures needed: ia64 m68k mips64 ppc ppc64 s390 s390x sh v850 x86-64

2003-05-04 20:45:18

by Kasper Dupont

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Ingo Molnar wrote:
>
> 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.

But in some cases you need 1MB+64KB. I think you should change the
start address from 0x00101000 to 0x00111000 so it does not overlap
the address space addressable from virtual 86 mode.

--
Kasper Dupont -- der bruger for meget tid p? usenet.
For sending spam use mailto:[email protected]
for(_=52;_;(_%5)||(_/=5),(_%5)&&(_-=2))putchar(_);

2003-05-04 22:10:11

by Richard Henderson

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sun, May 04, 2003 at 10:25:26AM -0400, Chuck Ebbert wrote:
> asmlinkage int sys_iopl(unsigned long unused)
> {
> struct pt_regs * regs = (struct pt_regs *) &unused; <== yuck!
[...]
> Shouldnt it be like this?
>
> asmlinkage int sys_iopl (struct pt_regs regs)

No, it should be like

int sys_iopl (struct pt_regs *regs)

and assembly language should push the proper address.

The struct-as-argument form allows the compiler to
smash the entire structure as it sees fit.

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

They're all wrong too.


r~

2003-05-04 23:44:33

by Chuck Ebbert

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

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


2003-05-05 00:29:28

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Followup to: <[email protected]>
By author: Richard Henderson <[email protected]>
In newsgroup: linux.dev.kernel
>
> On Sun, May 04, 2003 at 10:25:26AM -0400, Chuck Ebbert wrote:
> > asmlinkage int sys_iopl(unsigned long unused)
> > {
> > struct pt_regs * regs = (struct pt_regs *) &unused; <== yuck!
> [...]
> > Shouldnt it be like this?
> >
> > asmlinkage int sys_iopl (struct pt_regs regs)
>
> No, it should be like
>
> int sys_iopl (struct pt_regs *regs)
>
> and assembly language should push the proper address.
>
> The struct-as-argument form allows the compiler to
> smash the entire structure as it sees fit.
>

Hardly - it has to correspond to the ABI for the platform."

Presumably that's where the "asmlinkage" piece comes in.

-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
Architectures needed: ia64 m68k mips64 ppc ppc64 s390 s390x sh v850 x86-64

2003-05-05 03:02:13

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

Chuck Ebbert wrote:
>>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...
>

No, they don't, not if your mode of exploit is hacking return addresses
on the stack.

AMD64 makes this pretty easy, *ALL* user-space addresses are in the
"ASCII armour" area, and it supports exec-off. Apparently this is
currently off by default, but Andi Kleen says that they have identified
the bug that caused it and they're making it available as a kernel option.

-hpa

2003-05-05 07:02:23

by Ingo Molnar

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature


On 4 May 2003, Andi Kleen wrote:

> Ingo Molnar <[email protected]> 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

2003-05-05 13:23:00

by Jesse Pollard

[permalink] [raw]
Subject: Re: [Announcement] "Exec Shield", new Linux security feature

On Sunday 04 May 2003 02:03, Calin A. Culianu wrote:
> On Sat, 3 May 2003 [email protected] wrote:
> > On Sat, 03 May 2003 13:19:52 -0000, [email protected] said:
> > > 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()?
> >
> > This does absolutely nothing to stop an exploit from providing its own
> > inline version of execve(). There's nothing in libc that a process can't
> > do itself, inline.
> >
> > A better bet is using an LSM module that prohibits exec() calls from any
> > unauthorized combinations of running program/user/etc.
>
> Is that practical? I can see how with some daemons it would definitely be
> useful to prohibit exec calls (maybe things like BIND don't need to exec
> anything).. but some daemons do need to exec. An SMTPD may need to exec()
> some helper processes (postfix for instance has a whole slew of helper
> programs it uses).. and things like sshd need to exec a shell, etc..

What you actually would do is have the LSM module turn exec into MAY_EXEC_IF
where the IF is done to match security context information to the binary being
execed. ssh shouldn't exec (well most of the time anyway) a root shell.
Instead it should switch security context, (including a security id and
uid's/gids) first, then exec if the new security context is valid for what is
being execed. (and the new securid is not necessarily selected from kernel
mode - it may depend on network connection + user id/gids requested +
security level permitted)

More complicated, but the full security context being switched to cannot be
selected by the application itself.

> It's still a good idea though, since some daemons don't need to exec,
> ever. I guess this is one extra layer of protection. As Ingo said in his
> announcement, the more layers of protection you have, the better.. and the
> more difficult a cracker's job is.

true.

2003-05-05 16:07:53

by Ingo Molnar

[permalink] [raw]
Subject: [patch] exec-shield-2.4.21-rc1-C5


a new (-C5) release of the exec-shield patch can be found at:

http://redhat.com/~mingo/exec-shield/exec-shield-2.4.21-rc1-C5

Changes since -B6:

- removed the X_workaround - chstk can be used for equivalent
functionality. (issue raised by Yoav Weiss)

- increase SHLIB_BASE from 1MB to 1MB + 64KB, suggested by Alexandre
Julliard, to fix DOS loaders.

- fix Pentium/i386 compilation failure in fault.c. (reported by Johannes
Walch)

- fix signal return bug, found by [email protected].

- shared library address randomization, both within and outside the
ASCII-shield. This should make remote attacks a little bit more
difficult.

- process stack randomization. A number of other patches did this as
well, it generally helps. (There's no memory wasted because the stack
area left out will simply not be paged in.)

- turn off shlib relocation if the stack is executable. This is needed
for Wine, qemu and other apps that need the low memory range.

- do not show the wchan field of non-owned processes, and do not show the
maps file either. This should make it a little bit harder to guess
library locations for local attackers.

most of the new stuff in this patch (randomization, information filtering)
has been done in other patches as well (such as PaX, grsecurity, non-exec
stack patch, etc.) - i tried to filter out and add the ones that matter
most, do not introduce constraints and are thus uncontroversial.

bug reports, suggestions welcome.

Ingo