Exec Shield for the Linux Kernel
DarkOx writes "There is a new patch from Ingo Molnar which can prevent overflow attacks. The scoop from KernelTrap is as follows: Ingo Molnar has announced a new kernel-based security feature for Linux/x86 called 'Exec Shield'. He describes the patch, which is against the 2.4.20-rc1 kernel, as: '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.'"
Someone on lkml asked:
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?
and hpa replied to this:
x86-64 definitely does, and it's the default on Linux/x86-64.
Up to now, x86 chips have not been able to separate Read from Execute privileges for memory segments, which makes it hard to make stacks non-executable. This is excellent news for anyone looking forward to AMD's x86-64 chips...it keeps looking like they've done the Right Things.
The limitation is with most x86 processors. The new AMD x86-64 architecture does not suffer from this problem, and I believe linux on it defaults to nonexecutable stack (at least that's what was said on the LKML).
While it is true that in general even HUGE changes to the kernel rarely need an application recompile, and are transparent, sometimes this is not the case.
Consider the following:
Actually, even this patch is not entirely transparent. In order to best benefit from the ASCII-armor area, you will notice that in the readme text file they actually gave a patch to binutils to make executables try and use a lower address for their program text. Executables (unlike shared libraries) aren't relocatable and thus need to be re-linked in order to use a different (lower) address...
I've been screwing around with mprotect() and friends lately to write a exploit delivery system that can't be read by memory inspection tools on the target machine. While checking to see if similar techniques are possible on Windows, I found that the default addresses for PE/i386 executables' stack and text sections are all below 0x00ffffff. .text begins at 0x00400000, for example, and the stack is located below it.
:) I was wondering for the longest time why they chose those mappings by default until I saw this article today.
So it looks like Microsoft beat Ingo to it
-- thalakan
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.
No. The x86 page table has 12 bits per page table entry for storing page information. It contains a bit for R/W (read/write) which you can force a page read-only; and it contains a bit U/S (user/supervisor) which you can force a page usable only by the kernel. There is nothing which says "this page must not be executed as code". So Linux kernel actually has an interface that only some hardware provides. I don't think now it still has spare bit to give for executable bit.
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.
It is not about "do the right thing". The processor simply has no such bit, so there is no new "right thing" for it to do---it is already doing the right thing. The processor assumes that segmentation is used to enforce execute permission, so that each library code should be allocated a segment and inter-segment jumps and calls should be used to access them. In such way only read-only code segments are executable. Linux simply decided at the very beginning not to employ this facility.
ELF is not designed by Linus. And even if ELF is changed so that stack is not assumed executable by default (which probably break some programs that rely on executable stack), all computers from 386 to P4 will not benefit from it.