PaX

This is an old revision of this page, as edited by Bluefoxicy (talk | contribs) at 23:43, 21 May 2004 (Fixing headings, I AM braindamaged). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

PaX is a security patch for Linux that implements least privilege for memory page protections, which among others gives control over runtime code generation.

PaX offers Executable Space Protections to take advantage of or emulate the functionality of an NX bit, and Address Space Layout Randomization to obfuscate ret2libc attacks and other attacks that rely on known layout of the program's vm space.

Executable space protections

The major feature of PaX is the Executable Space Protection it offers. These protections take advantage of the NX bit on certain processors to prevent the execution of arbitrary code. This staves off attacks involving code injection or shellcode. On processors where there is no NX bit, PaX can emulate the functionality of one in various ways.

When the Executable Space Protections are enabled, PaX guarantees that no pages will be marked both writable and executable.

PAGEEXEC

PAGEEXEC uses or emulates an NX bit. On processors which do not support a hardware NX, each page is given an emulated NX bit. The method used to do this is based on the architecture of the CPU.

PAGEEXEC has the advantage of not cutting the address space in half; tasks still each get a 3GiB virtual ramspace rather than a 1.5/1.5 split. However, for emulation, it is slower than SEGMEXEC and caused a severe performance detriment until the PaX release for Linux 2.6.5 on May 14, 2004 at 22:35 GMT.

SEGMEXEC

SEGMEXEC emulates the functionality of an NX bit by splitting the address space in half and mirroring the code mappings accross the address space. When there is an instruction fetch, the fetch is translated accross the split. If the code isn't mapped there, then the program is killed.

SEGMEXEC cuts the task's virtual memory space in half. Under normal circumstances, programs get a VM space 3GiB wide, which has physical memory mapped into it. Under SEGMEXEC, this becomes a 1.5/1.5 GiB split, with the top half used for the mirroring. Despite this, it does increase performance if you must do emulation on IA-32 (x86) architectures. Also, it is good to note that the mapping in the upper and lower half of the memory space is to the same physical memory page, and so does not double your ram usage.

Restricted mprotect()

PaX is supposed to guarentee that no ram is both writable and executable. One function, the mprotect() function, changes the permissions on a memory area. The Single Unix Specification defines mprotect() with the following note in its description:

If an implementation cannot support the combination of access types specified by prot, the call to mprotect() shall fail.

The PaX implimentation does not allow a memory page to have permissions PROT_WRITE and PROT_EXEC both enabled when mprotect() restrictions are enabled for the task; any call to mprotect() to set both (PROT_WRITE | PROT_EXEC) at the same time will fail due to EACCESS (Permission Denied).

Address space layout randomization

Address Space Layout Randomization, or ASLR, is a technique of countering arbitrary execution of code, or ret2libc attacks. These attacks involve executing already existing code out of the order intended by the programmer.

ASLR shuffles the stack base and heap base around in virtual memory when enabled. It also optionally randomizes the mmap() base and the executable base of programs. This makes attacks requiring the known location of these areas into a probability function of high magnitude.

Randomized mmap() base

When Randomized mmap() base is enabled, PaX randomly chooses an offset for all mmap() calls made without a specific offset, and for all non-fixed mmap() calls made with a specific offset which cannot be satisfied at that offset. This causes all dynamicly linked code, i.e. shared objects, to be mapped at a different, randomly selected offset every time. Attackers requiring a function in a certain library must guess where that library is loaded in virtual memory space to call it.

When ET_DYN executables--that is, executables compiled with position independant code in the same way that shared libraries are--are loaded, their base is also randomly chosen, as they are mmap()ed into ram just like regular shared objects.

Randomized ET_EXEC base

PaX is able to map non-position-independant code randomly into ram; however, this poses a few problems. First, it incurs some extra performance overhead. Second, it causes occasional false alarms, bringing PaX to kill the process for no reason. It is strongly recommended that executables be compiled ET_DYN, so that they are 100% position independent code.

History

The oldest documentation for PaX is that of the original PAGEEXEC implimentation, dated November 16, 2000 18:00 GMT in the documentation directory. The documentation notes the following history:

 2000.08.06 initial document
 2000.10.01 pax/linux implementation was born
 2000.10.22 fixed minor inaccuracies
 2000.10.27 added copy-on-write issue
 2000.10.28 finished linux implementation description
 2000.11.05 fixed VM_IO handling, SysV IPC shared memory became NOEXEC
 2000.11.16 fixed race on page directory/table accesses

See also