While many C/C++ zealots shun garbage collection as a leaky abstraction, advocates of languages such as Java and Lisp often like to describe languages which allow for manual memory management as "unsafe". This is because most operating systems do not mark pages with executable data as read only in a process context, and writable pages as non-executable, primarily because the IA32 architecture provided no mechanism for this in protected mode. Consequently anyone who can overwrite any part of the memory with CPU instructions and knows that the instruction pointer will at some point fall in that range, or can overwrite the address used by a jump instruction with the location of their own instructions (such as, say, the return pointer of a stack frame) can execute arbitrary code.
Linux has taken a step towards implementing a security feature which many architectures, most notably Solaris/SPARC, have had for years, a non-executable user stack, on the new AMD64 architecture which sports page permissions. You can read about it here:
http://kerneltrap.org/node/view/3240
What they've implemented is typically described as a "non-executable user stack", namely that if the instruction pointer points at a page which does not have an execute bit, the CPU generates an exception which can be handled in the same way by the kernel as an attempt to access protected memory in process context. Any processes attempting to execute data in the user stack will now die with "Segmentation fault" rather than being exploitable.
Of course, this is only half of the solution as executable pages can still be modified in process context. This is why even with Solaris's noexec_user_stack enabled for sparcv8 binaries (and it's the default behavior of sparcv9 binaries) we still see buffer overflows on Solaris... if someone is able to maliciously write past a page boundary into an executable page they can still exploit a buffer overflow.
Let's hope Linux takes the extra step and implements executable pages which are read-only in process context. This will likely require some additional system calls for proper dynamic linker thunking, but that can all be abstracted in the kernel and through libdl.
With Intel's adoption of both the AMD64 instruction set and its page permission features, I hope we see this silver bullet to buffer overflows applied to Linux and other architectures in the next few years.
But suffice it to say the end of buffer overflows is here, and the answer needn't necessarily be managed code
Linux has taken a step towards implementing a security feature which many architectures, most notably Solaris/SPARC, have had for years, a non-executable user stack, on the new AMD64 architecture which sports page permissions. You can read about it here:
http://kerneltrap.org/node/view/3240
What they've implemented is typically described as a "non-executable user stack", namely that if the instruction pointer points at a page which does not have an execute bit, the CPU generates an exception which can be handled in the same way by the kernel as an attempt to access protected memory in process context. Any processes attempting to execute data in the user stack will now die with "Segmentation fault" rather than being exploitable.
Of course, this is only half of the solution as executable pages can still be modified in process context. This is why even with Solaris's noexec_user_stack enabled for sparcv8 binaries (and it's the default behavior of sparcv9 binaries) we still see buffer overflows on Solaris... if someone is able to maliciously write past a page boundary into an executable page they can still exploit a buffer overflow.
Let's hope Linux takes the extra step and implements executable pages which are read-only in process context. This will likely require some additional system calls for proper dynamic linker thunking, but that can all be abstracted in the kernel and through libdl.
With Intel's adoption of both the AMD64 instruction set and its page permission features, I hope we see this silver bullet to buffer overflows applied to Linux and other architectures in the next few years.
But suffice it to say the end of buffer overflows is here, and the answer needn't necessarily be managed code
Comment