| |||||||||
NX stands for "no execute", a technology used in CPUs such as Sun's Sparc, Transmeta's Efficeon, and newer 64-bit x86 processors to prevent code from being executed on areas of memory flagged with an NX bit. This feature significantly lowers the probability of crackers exploiting buffer overflows and increases overall system security.
An operating system with the ability to emulate and/or take advantage of an NX bit may prevent the stack and heap memory areas from being executable, and may prevent executable memory from being writable. This helps to prevent certain buffer overflow exploits from succeeding, particularly those that inject and execute code, such as the Sasser and Blaster worms. These attacks rely on some part of memory, usually the stack, to be both writable and executable; if it is not, the attack fails.
Many operating systems implement or have available an NX policy, and some implement or have available NX emulation. Here is a list of such systems in alphabetical order, each with technologies ordered from newest to oldest.
At the head of each technology, there is a data table which gives the major features each technology supports. The nature of these technologies warrants the expedient diffusion of information about them, and so these tables are supplied to give a summary of the text below. The table is structured as below.
A technology supplying Architecture Independent emulation will be functional on all processors which aren't hardware supported. The "Other Supported" line is for processors which allow some grey-area method, where an explicit NX bit doesn't exist yet hardware allows one to be emulated in some way.
Linux itself supports standard hardware NX, now in 32 bit mode on 64-bit CPUs via Ingo Molnar's NX enabler patch as well as in 64 bit mode on CPUs that support it (these include current 64-bit CPUs of AMD and future CPUs announced by Intel, Transmeta and VIA). Linus Torvalds has taken an interest in the NX patch, and believes it may be wise to have NX enabled by default; thus, it has been merged in 2.6.8. This is significant on 32-bit x86 kernels, which may run on both 32-bit x86 CPUs and 64-bit x86 compatible CPUs. A 32-bit x86 kernel would not normally expect the NX bit that an AMD64 or IA-64 supplies; the NX enabler patch assures that these kernels will attempt to use the NX bit if present.
As of this patch, Linux fully utilizes the hardware NX bit in supporting CPUs from Intel, AMD, Transmeta and VIA. The NX patch was released to the Linux kernel mailing list in June, 2004.
Non-execute functionality has also been present for other non-x86 processors supporting this functionality for many releases.
Redhat kernel developer Ingo Molnar released a Linux kernel patch named Exec shield to approximate and utilize NX functionality on 32-bit x86 CPUs. Later, he released the Linux NX patch that supports hardware NX on 32-bit kernels.
The Exec Shield patch was released to the Linux Kernel Mailing List May 2, 2003. It was rejected for merging with the base kernel because it involved some intrusive changes to core code in order to handle the complex parts of the emulation trick.
The PaX NX technology can emulate an NX bit or NX functionality, or use a hardware NX bit. PaX works on x86 CPUs that do not have the NX bit, such as 32-bit x86.
The PaX project originated October 1, 2000. It was later ported to 2.6, and is at the time of this writing still in active development.
The Linux kernel still does not ship with PaX (as of May, 2004); the patch must be merged manually.
Windows XP Service pack 2 and the forthcoming Windows Longhorn ship with NX capabilities. The service pack can be installed onto existing installations, and future versions of Windows will ship with it preinstalled. Most notably, Windows uses NX protection on critical Windows services exclusively by default. Users must manually enable full NX protection for everything else.
Here, features of the NX technologies will be compared and contrasted.
Generally, NX bit emulation is only available on x86 CPUs. The sections within dealing with emulation are only concerned with x86 CPUs unless otherwise stated.
While it has been proven that some NX bit emulation methods incur an extremely low overhead, it has also been proven that such methods can become inaccurate. On the other hand, other methods may incur an extremely high overhead and be absolutely accurate. No method has been discovered as of yet without a significant trade-off, whether in processing power, accuracy, or virtual memory space.
Overhead is the amount of extra CPU processing power that is required for each technology to function. It is important because technologies which somehow emulate or supply an NX bit will usually impose a measurable overhead; while using a hardware supplied NX bit will impose no measurable overhead. All technologies will create overhead due to the extra programming logic that must be created to control the state of the NX bit for various areas of memory; however, evaluation usually handled by the CPU itself when a hardware NX bit exists, and thus produces no overhead.
On CPUs supplying a hardware NX bit, none of the listed technologies imposes any significant measurable overhead unless explicitly noted.
Exec Shield's legacy CPU support approximates (Ingo Molnar's word for it) NX emulation by tracking the upper code segment limit. This imposes only a few cycles of overhead during context switches, which is for all intents and purposes immeasurable.
PaX supplies two methods of NX bit emulation, called SEGMEXEC and PAGEEXEC. These are listed in the BambooWeb article for PaX.
The SEGMEXEC method imposes a measurable, but low overhead, typically less than 1%. This is a constant scalar incurred due to the virtual memory mirroring used. SEGMEXEC also has the effect of halving the task's virtual address space, allowing the task to access less memory than it normally could. This is not a problem until the task requires access to more than half the normal address space, which is rare. SEGMEXEC does not cause programs to use more system memory (i.e. RAM); it only restricts how much they can access. On 32-bit CPUs, this becomes 1.5GiB rather than 3GiB.
PaX supplies a method similar to Exec Shield's approximation in the PAGEEXEC as a speedup; however, when higher memory is marked executable, this method loses its protections. In these cases, PaX falls back to the older, variable overhead method used by PAGEEXEC to protect pages below the CS limit, which may become a quite high overhead operation in certain memory access patterns.
When the PAGEEXEC method is used on a CPU supplying a hardware NX bit, the hardware NX bit is used; no emulation is used, thus no significant overhead is incurred.
Some technologies approximately emulate (or approximate) an NX bit on CPUs which do not support them. Others strictly emulate an NX bit for these CPUs, but decrease performance or virtual memory space significantly. Here, these methods will be compared for accuracy.
All technologies listed here are 100% accurate in the presence of a hardware NX bit, unless otherwise stated.
For legacy CPUs without an NX bit, Exec Shield fails to protect pages below the code segment limit; an mprotect() call to mark higher memory, such as the stack, executable will mark all memory below that limit executable as well. Thus, in these situations, Exec Shield's schemes fails. This is the cost of Exec Shield's low overhead (see above).
SEGMEXEC does not rely on such volatile systems as that used in Exec Shield, and thus does not encounter conditions in which finegrained NX bit emulation cannot be enforced; it does, however, have the halving of virtual address space mentioned above.
PAGEEXEC will fall back to the original PAGEEXEC method used before the speed-up when data pages exist below the upper code segment limit. In both cases, PaX' emulation remains 100% accurate; no pages will become executable unless the operating system explicitly makes them as such.
It is also interesting to note that PaX supplies mprotect() restrictions to prevent programs from marking memory in ways which produce memory useful for a potential exploit. This policy causes certain applications to cease to function; but can be disabled for affected programs.
Some technologies allow executable programs to be marked so that the operating system knows to relax the restrictions imposed by the NX technology for that particular program. Various systems provide various controls; such controls are described here.
Exec Shield supplies executable markings. Exec Shield only checks for two ELF header markings, which dictate whether the stack or heap needs to be executable. These are called PT_GNU_STACK and PT_GNU_HEAP, respectively. Exec Shield allows these controls to be set for both binary executables and for libraries; if an executable loads a library requiring a given restriction relaxed, the executable will inherit that marking and have that restriction relaxed.
PaX supplies fine-grained control over protections. It allows individual control over the following functions of the technology for each binary executable:
See the PaX article for more details about these restrictions.
PaX completely ignores both PT_GNU_STACK and PT_GNU_HEAP. There was a point in time when PaX had a configuration option to honor these settings; that option has henceforth been intentionally removed for security reasons, as it was deemed not useful. The same results of PT_GNU_STACK can normally be attained by disabling mprotect() restrictions, as the program will normally mprotect() the stack on load. This may not always be true; for situations where this fails, simply disabling both PAGEEXEC and SEGMEXEC will effectively remove all executable space restrictions, giving the task the same protections on its executable space as a non-PaX system.