Hardened/PaX Quickstart

From Gentoo Wiki
Revision as of 11:53, 12 September 2013 by SwifT (Talk | contribs)

Jump to: navigation, search

Understanding and working with PaX in Hardened Gentoo.

What is Hardened Gentoo?

The Hardened Gentoo project focuses on adding features to a Gentoo system that help resist security compromises. The approach is not always systematic, and many features that enhances security are added. Some of these compliment one another (eg. PIE from toolchain hardening and ASLR from PaX kernel hardening), and some are mutually exclusive (eg. SELinux and Grsecurity's RSBAC kernel hardening). This document focuses on PaX which adds security enhancement to that area between both kernel and user land.

What is PaX?

PaX is a patch to the Linux kernel that provides hardening in three ways.

1. The first protection provided by PaX is a judicious enforcement of non-executable memory. This prevents a common form of attack where executable code is inserted into the address space of a process by an attacker and then trigger, thus hijacking the process and possibly escalating privileges. The typical vector for the insertion is via user provided data that find its way into executable memory. By ensuring that "data" only lives in memory which is non-executable, and that only "text" is found in memory which is executable, PaX pre-emptively protects against this class of attacks.

Try running the following with PaX's MPROTECT enforced and then not enforced to see this feature in action:

Codemmap-rwx.c: violate MPROTECT with RWX mmap

/*
 * Contrast compiling with:
 *   gcc -UBAD -o mmap-rw mmap-rwx.c
 *   gcc -DBAD -o mmap-rwx mmap-rwx.c
 */
  
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
  
int main()
{
	size_t *m;
  
#ifdef BAD
	m = mmap( NULL, 1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
#else
	m = mmap( NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
#endif
  
	if( m == MAP_FAILED )
		printf("mmap failed: %s\n", strerror(errno));
	else
		printf("mmap succeeded: %p\n", m);
  	
        return 0;
}

Similarly, try running the following with EMULTRAMP both enabled and disabled. This convoluted code forces gcc to set up a trampoline for the nested function f2(). The trampoline is executable code which lives on the stack and could allow the user to inject their own code via the variable i.

Codetrampoline.c: force gcc to generate a trampoline

/*
 * Contrast compiling with:
 *   gcc -DTRAMPOLINE -o trampoline trampoline.c
 *   gcc -UTRAMPOLINE -o trampoline trampoline.c
 *
 */
  
#include <stdio.h>
  
typedef void (*fptr)(void) ;
  
void f0(fptr f)
{
        (*f)();
}
  
void f1()
{
	int i ;
	printf("Enter an integer: ");
	scanf("%d", &i);
  	
        void f2()
	{
		printf("%d: Bouncey bouncey bounce!\n", i);  
        }
  
#ifdef TRAMPOLINE
	f0(f2);
#endif
}
  
int main ()
{
	f1() ;
	return 0;
}

2. The second is Address Space Layout Randomization (ASLR). This provides a randomization of the memory map of a process (as reported, for example, by pmap) and thus makes it harder for an attacker to find the exploitable code within that space. Each time a process is spawned from a particular ELF executable, its memory map is different. Thus exploitable code which may live at 0x00007fff5f281000 for one running instance of an executable may find itself at 0x00007f4246b5b000 for another. While the vanilla kernel does provide some ASLR, a PaX patched kernel increases that. Furthermore, when an application is built as a Position Independent Executable (PIE ), even the base address is randomized. Try repeatedly running the following on both a vanilla and PaX kernel, with and without PIE:

Codeaslr-test.c: randomize base addess for PIE

/*
 * Contrast compiling with:
 *   gcc -o aslr-test-withpie -fPIC -pie aslr-test.c
 *   gcc -o aslr-test-without -fno-PIC -nopie aslr-test.c
 *
 */
  
#include <stdio.h>
  
void doit()
{
        ;
        return ;
}
  
int main()
{
        printf("main @ %p\n", main);
        printf("doit @ %p\n", doit);
        return 0;
}

For more information on PIE, see our documentation on the Hardened Toolchain .

3. Finally, the PaX patches provide some miscellaneous hardening: erasing the stack frame when returning form a system call, refusing to dereference user land pointers in some contexts, detecting overflows of certain reference counters, correcting overflows of some integer counters, enforcing the size on copies between kernel and user land, and provided extra entropy.

More information on PaX can be found on its official homepage, http://pax.grsecurity.net .

Understanding PaX

The first step in working with PaX is to configure and boot a PaX patched kernel. Depending on whether or not you've configured PaX for SOFTMODE or non-SOFTMODE, the kernel will automatically start enforcing memory restrictions and address space randomization on all running processes. Ideally you shouldn't have to do anything else; however, for problematic executables in non-SOFTMODE, a second step is required: you may have to relax certain PaX restrictions on a per ELF object basis. This is done by tweaking the PaX flags which are read by the kernel when the ELF is loaded into memory and execution begins. This second step is usually straight forward except when the ELF object that requires the relaxation is a library. In that case, the library's flags have to be back ported to the executable that links against it because when PaX enforces/relaxes its features, it does so on the basis of the executable's flags, not those of the libraries it links against. We will discuss both steps in detail below, but first we need an overview of PaX's features. We'll summarize these here, and for more details, we refer the reader to the official PaX documentation .

SOFTMODE: If this option is selected, PaX protection will not be enforced by default for those features which can be turned on or off at runtime, so this is the "permit by default" mode in contrast to the "forbid by default" which is obtained when this option is not selected. In SOFTMODE, the user must explicitly mark executables to enforce PaX protections, whereas in non-SOFTMODE, the user must explicitly mark to relax PaX protections.

Enforce non-executable pages:

PAX_NOEXEC - This option enables the protection of allocated pages of memory as non-executable if they are not part of the text segment of the running process. It is needed for PAGEEXEC, SEGMEXEC and KERNEXEC. PAGEEXEC - The kernel will protect non-executable pages based on the paging feature of the CPU. This is sometimes called "marking pages with the NX bit" in other OSes. This feature can be controlled on a per ELF object basis by the PaX P and p flags. SEGMEXEC - This is like PAGEEXEC, but based on the segmentation feature of the CPU and it is controlled by the PaX S and s flags. Note that SEGMEXEC is only available on CPUs that support memory segmentation, namely x86. EMUTRAMP - The kernel will emulate trampolines (snippets of executable code written on the fly) for processes that need them, eg. nested functions in C and some JIT compilers. Since trampolines try to execute code written by the process itself to memory marked as non-executable by PAGEEXEC or SEGMEXEC, the PaX kernel would kill any process that tries to make use of one. EMUTRAMP allows these processes to run without having to fully disable enforcement of non-executable memory. This feature can be controlled on a per ELF object basis by PaX E and e flag. MPROTECT - The kernel will prevent the introduction of new executable pages into the running process by various techniques: it will forbid the changing of the executable status of pages, or the creation of anonymous RWX mappings, or making RELRO data pages as writable again. It is controlled on a per ELF object basis by the PaX M and m flag. KERNEXEC - This is the kernel land equivalent of PAGEEXEC and MPROTECT. It cannot be disabled during while the kernel is running.

Enhanced Address Space Layout Randomization (ASLR):

PAX_ASLR - The kernel will expand the number of randomized bits for the various section of the address space. This option is needed for RANDMMAP, RANDKSTACK and RANDUSTACK. RANDMMAP - The kernel will use a randomized base address for mmap() requests that do not specify one via the MAP_FIXED flag. It is controlled by the PaX R and r flags. RANDKSTACK - The kernel will randomize every task's kernel stack on all system calls. It cannot be disable while the kernel is running. RANDUSTACK - The kernel will randomize every task's userland stack. This feature can be controlled on a per ELF binary basis by the PaX R and r flags.

Miscellaneous Memory Protection:

None of the following features can be disabled while the kernel is running: STACKLEAK - The kernel will erase its stack before it returns from a system call. This feature cannot be disabled while the kernel is running. UDEREF - The kernel will not dereference userland pointers in contexts where it expects only kernel pointers. This feature cannot be disabled while the kernel is running. REFCOUNT - The kernel will detect and prevent overflowing various (but not all) kinds of object reference counters. USERCOPY - The kernel will enforce the size of heap objects when they are copied in either direction between the kernel and userland. SIZE_OVERFLOW - The kernel recomputes expressions of function arguments marked by a size_overflow attribute with double integer precision. LATENT_ENTROPY - The kernel will use early boot code to generate extra entropy, which is especially useful on embedded systems.

As stated above, some PaX features can be enforced (in the case of SOFTMODE) or relaxed (in the case of non-SOFTMODE) on a "per ELF object" basis. These are PAGEEXEC, EMULTRAP, MPROTECT, RANDMMAP and SEGMEXEC and these are respectively controlled by the following flags: P, E, M, R, S and p, e, m, r, s. The upper case mean "enforce" in SOFTMODE and the lower case mean "relax" in non-SOFTMODE. A third possibility is that neither the enforce or relax flags are set, in which case the kernel simply uses the default for that particular protection. Eg. if neither P nor p is set on an ELF object, then the kernel will not enforce PAGEEXEC in SOFTMODE and will enforce it in non-SOFTMODE.

Currently the PaX patches support three ways of doing PaX markings: EI_PAX, PT_PAX and XATTR_PAX. EI_PAX places the PaX flags in bytes 14 and 15 of the e_ident field of an ELF objects's header. But this is broken in recent versions of glibc and is no longer supported. (See bug #365825 ) PT_PAX places the flags in a ELF objects's program header called PAX_FLAGS. This has the advantage the that flags are in the body of the object and will always be carried with it when copied; but, it has the disadvantage that the object must have th PAX_FLAGS program header to work. Most Linux distributions don't build their executables and libraries with this program header, and adding it is problematic: there may not be enough space in the ELF object to add it or converting a GNU_STACK program header, which is not used by the PaX kernel, might later cause problems under other kernels if the object is exported. In the worst case, changing the ELF binary will break self-checking executables which detect that they have been "tampered" with. (See bug #100507 ).

While PT_PAX is still supported, the preferred approach is to use XATTR_PAX which places the PaX flags in a file system's extended attributes. This has the advantage that it does not modify the ELF object in any way, but the disadvantage that the filesystems which house these objects, and the utilities used to copy, move and archive, them, must support xattrs. In the case of Gentoo and portage, this means that tmpfs must support the user.pax.* xattr namespace in which the PaX flags are placed, not just the security.* and trusted.* namespaces. (Note: user.pax.* is the subspace of user.* which will be used for PaX related xattr information. We do not enable the entire user.* namespace in tmpfs to reduce the risk of attack vectors via that path.)

One final caveat about the two supported methods of doing PaX markings: the PaX kernel allows you to enable both PT_PAX and XATTR_PAX, but if you do so, it will not impose the markings unless the same flags are found in both locations. For this reason, we do not recommend enabling both, even for migration which we describe below.

Building a PaX Kernel

The Hardened Gentoo team maintains and supports the hardened-sources package, which we will cover here. Other in tree kernel sources may have PaX, and much of what we say may apply, but you will have to work through the differences yourself. The hardened-sources come with the Grsecurity patches ( http://grsecurity.net/ ), which bundle the PaX patches. If you want only the PaX patches, these can be obtained in isolation from http://www.grsecurity.net/~paxguy1/ . If you are interested in learning more about Grsecurity hardening in general, we cover that in our Grsecurity Quickstart .

Emerging a hardened-sources kernel places the kernel source tree at /usr/src, but it does not configure it for you. It is now up to you to make sure PaX is configured so that it enforces or relaxes what you want. Below we will concentrate on recommended configurations, but feel free to deviate. The previous section should have given you some idea as to what each of the options provide so you can make intelligent choices. We recommend tarting off with as much hardening as possible and relaxing only when there is no other workaround.

As stated, the PaX patches are bundled with Grsecurity, so the PaX configuration options are found under that menu in Security Options -> Grsecurity -> Customize Configuration -> PaX . You also have the option of selecting one of Grsecurity's preconfigured profiles at Security Options -> Grsecurity -> Configuration Method . These will give you a meaningful starting point configuration for PaX.

If configuring for only PT_PAX, the following should be sufficient. Note that since we are trying to show the configuration options for both x86 and amd64, we've marked where the differences lie with a > in the left most column.

Kernel configurationKernel configuration for PT_PAX

[*] Enable various PaX features
  
PaX Control ->
  
 [ ] Support soft mode
 [ ] Use legacy ELF header marking
 [*] Use ELF program header marking
 [ ] Use filesystem extended attributes marking
     MAC system integration (none)  --->
  
Non-executable page ->
  
 [*] Enforce non-executable pages
 [*]   Paging based non-executable pages
 [*]   Segmentation based non-executable pages                       <--- Not available on amd64.
 [*] Emulate trampolines
 [*] Restrict mprotect()
 [ ]   Use legacy/compat protection demoting (read help)
 [ ]   Allow ELF text relocations (read help)
 [*] Enforce non-executable kernel pages
     Return Address Instrumentation Method (or)  --->                <--- Not available on x86.
     (4) Minimum amount of memory reserved for module code           <--- Not available on amd64.
  
Address Space Layout Randomization ->
  
 [*] Address Space Layout Randomization
 [*] Randomize kernel stack base
 [*] Randomize user stack base
 [*] Randomize mmap() base
  
Miscellaneous hardening features  --->
  
 [*] Sanitize all freed memory
 [*] Sanitize kernel stack
 [*] Prevent invalid userland pointer dereference
 [*] Prevent various kernel object reference counter overflows
 [*] Harden heap object copies between kernel and userland
 [*] Prevent various integer overflows in function size parameters
 [*] Generate some entropy during boot

Preferably, we should opt for XATTR_PAX flags. In that case, all of the above can remain in place, but we would change the PaX Control configuration:

Kernel configurationKernel configuration with XATTR_PAX flags

PaX Control ->
  
 [ ] Support soft mode
 [ ] Use legacy ELF header marking
 [ ] Use ELF program header marking
 [*] Use filesystem extended attributes marking
     MAC system integration (none)  --->

Since the PaX flags will now live on the extended attributions of your filesystems, you would need to enable xattr on those filesystems, but the PaX team has already set up a dependency. Eg. for Ext4 we have

Kernel configurationAutomatic selection of EXT4_FS_XATTR by XATTR_PAX_FLAGS

File systems  --->
 <*> The Extended 4 (ext4) filesystem
 -*-   Ext4 extended attributes
 [ ]     Ext4 POSIX Access Control Lists
 [ ]     Ext4 Security Labels
 [ ]   EXT4 debugging support      

Here Ext4 extended attributes was automatically selected by PAX_XATTR_PAX_FLAGS [=y] && GRKERNSEC [=y] && PAX [=y] && EXT4_FS [=y] . Nonetheless, in case you are using some exotic filesystem which doesn't have this this selection dependency, you may want to check and then file a bug report to have your filesystem better supported with respect to PaX.

PaX Control

As we mentioned above, there are five PaX protections that can be enforced (in SOFTMODE) or relaxed (in non-SOFTMODE) on a per ELF object basis: PAGEEXEC, EMULTRAP, MPROTECT, RANDMMAP and SEGMEXEC. The later, SEGMEXEC, is only available on x86 CPUs which support segmentation, unlike paging which is supported on all CPUs, even x86. Since some programs break for one reason or another under full PaX enforcement, we are faced with the choice of either fixing the code to work with PaX or relaxing one or more of these protections. In practice, "fixing the code" may be very difficult and we resort to the latter. The general approach should be to try full enforcement, and if something breaks, use dmesg to obtain a report from the kernel regarding why and then relax that particular protection. Even this is not generally needed on a Gentoo system because the ebuilds should set the correct flags for you via the pax-util.eclass. If you find that you have to set your own flags, we would ask that you file a bug report.

Generally setting the PaX flags is straightforward, but the user should keep a few things in mind:

1) One can set either PT_PAX and/or XATTR_PAX flags on the ELF object independently of one another. Similarly, the kernel can be configured to read either, both or neither fields. It is up to you to make sure that you set the flags in the field being used by the kernel to get the desired results. For example, if you have PT_PAX="Pe---" while XATTR_PAX missing on the object, but the kernel is configured only to use XATTR_PAX, you may not get the desired result!

2) The recommended approach is to mark both PT_PAX and XATTR_PAX fields identically on the objects whenever possible, and set the kernel to read only XATTR_PAX. The "whenever possible" is where things get complicated and the two fields may not wind up containing the same flags. If the ELF does not contain a PAX_FLAGS program header, PT_PAX marking will fail. However, the absence of this program header will not affect XATTR_PAX markings. If the ELF is busy (ie. there is a running process making use of the ELF's text), then one can read the PT_PAX flags but not set them. Again, this does not affect setting or getting XATTR_PAX flags. On the other hand, if you are using any file systems which do not support extended attributes, then XATTR_PAX marking will fail on those file systems while PT_PAX marking is uneffected, except as already stated. This can be fairly subtle because copying a file from a file system with xattrs to one without, and then back again will drop the XATTR_PAX flags. Or tarring with an older version of tar which does not preserve xattrs will again drop our flags.

3) The PaX flags are only enforced when a process is loaded from an ELF executable. This executable in turn usually links dynamically against shared objects in memory. Using `cat /proc/<pid>/status | grep PaX` gives you the resulting PaX enforcement on the running process with PID=<pid>. But since the executable and shared objects can have different flags, the question arises, which ones are used to determine the final running PaX enforcements? The answer is the executable for reasons of control and security. If the libraries were to set the runtime PaX enforcement, then which of the libraries would "win" if an executable linked against many? And one overly relaxed library could relax the privileges on many executables that link against it. Eg. Relaxing all PaX protection on glibc would effectively turn PaX off on one's system. Nonetheless, it may be the code in the library itself that needs the relaxation of some PaX enforcement. In that case, one has to "back port" the flags from the library to the executable that uses it.

Below we describe the utilities provided on a Gentoo system for working PaX markings. There are several since as PaX evolved, new features were needed. Each one emphasizes a different need with respect to the above caveats.

1. paxctl

This is the traditional upstream package for setting PaX flags. It is limited only in that it sets PT_PAX only, not XATTR_PAX. It is provided by emerging sys-apps/paxctl. It does have one functionality that no other utility has: it can either create a PAX_FLAGS program header or convert a GNU_STACK to PAX_FLAGS. Both of these are not recommended since they can break the ELF under certain circumstances. However, in the extreme case that you cannot use XATTR_PAX (eg. you can't use file systems that support extended attributes) and you are dealing with an ELF object that wasn't build with a PAX_FLAGS program header, then these options are available to you via this utility.

Here is a synopsis of its usage:

root # paxctl -h
PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>
  
usage: paxctl <options> <files>
  
options:
	-p: disable PAGEEXEC		-P: enable PAGEEXEC
	-e: disable EMUTRAMP		-E: enable EMUTRAMP
	-m: disable MPROTECT		-M: enable MPROTECT
	-r: disable RANDMMAP		-R: enable RANDMMAP
	-x: disable RANDEXEC		-X: enable RANDEXEC
	-s: disable SEGMEXEC		-S: enable SEGMEXEC
  
	-v: view flags			-z: restore default flags
	-q: suppress error messages	-Q: report flags in short format
	-c: convert PT_GNU_STACK into PT_PAX_FLAGS (see manpage!)
	-C: create PT_PAX_FLAGS (see manpage!)

Note that paxctl also reports on an older PaX protection called RANDEXEC. This is now deprecated --- the randomization of the base address of a processes now simply part of ASLR on all executables build ET_DYN rather than EX_EXEC. Here is paxctl in action:

root # paxctl -v /usr/bin/python3.2
PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>
  
- PaX flags: -----m-x-e-- [/usr/bin/python3.2]
	MPROTECT is disabled
	RANDEXEC is disabled
	EMUTRAMP is disabled
  
# paxctl -P /usr/bin/python3.2 
# paxctl -v /usr/bin/python3.2 
PaX control v0.7
Copyright 2004,2005,2006,2007,2009,2010,2011,2012 PaX Team <pageexec@freemail.hu>
  
- PaX flags: P----m-x-e-- [/usr/bin/python3.2]
	PAGEEXEC is enabled				<--- Note: this added to the earlier flags, it didn't overwrite them.
	MPROTECT is disabled
	RANDEXEC is disabled
	EMUTRAMP is disabled

2. getfattr setfattr

These are not PaX specific utilities but are general utilities to set a file's extended attributes. On Gentoo, they are provided by emerging sys-apps/attr. Since XATTR_PAX uses the user.* namespace, specifically it uses "user.pax.flags", you can use set/getfattr to work with this field. However, keep in mind that setfattr and getfattr know nothing about PaX, so they will not perform any sanity checking of what you are putting into that field. Only if you set user.pax.flags to some meaningful combination of the chars PpEeMmRr will the kernel respect your choice, else it falls back on the default. The following listing gives examples.

The following is an example of their usage for XATTR_PAX:

root # getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="em"
root # setfattr -n user.pax.flags -v P /usr/bin/python3.2
root #
getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="P"						<--- Note: this overwrote the earlier flags, it didn't add to them.
root # setfattr -n user.pax.flags -v "Hi Mom, wish you were here." /usr/bin/python3.2
root #
getfattr -n user.pax.flags /usr/bin/python3.2
getfattr: Removing leading '/' from absolute path names
# file: usr/bin/python3.2
user.pax.flags="Hi Mom, wish you were here."			<--- Mom appreciates it, but PaX does not.  There is no sanity checking.

3. paxctl-ng

paxctl-ng is the new swiss army knife of working with PT_PAX an XATTR_PAX markings. It can be built with support for just one or the other or both types of markings. When built with support for both, it can copy PT_PAX to XATTRP_PAX fields or vice versa, to make sure you have consistency. In sum, it can do everything paxctl and set/getfattr can do, except it will not try to create or convert a PAX_FLAGS program header. This is discouraged and should only be use in the corner case mentioned above. Here is a synopsis of its usage:

Codepaxctl-ng -h

Package Name : elfix 0.7.1
Bug Reports  : http://bugs.gentoo.org/
Program Name : paxctl-ng
Description  : Get or set pax flags on an ELF object
  
Usage        : paxctl-ng -PpEeMmRrSsv ELF | -Zv ELF | -zv ELF
             : paxctl-ng -Cv ELF | -cv ELF | -dv ELF
             : paxctl-ng -Fv ELF | -fv ELF
             : paxctl-ng -Lv ELF | -lv ELF
             : paxctl-ng -v ELF | -h
  
Options      : -P enable PAGEEXEC	-p disable  PAGEEXEC
             : -E enable EMUTRAMP	-e disable  EMUTRAMP
             : -M enable MPROTECT	-m disable  MPROTECT
             : -R enable RANDMMAP	-r disable  RANDMMAP
             : -S enable SEGMEXEC	-s disable  SEGMEXEC
             : -Z all secure settings	-z all default settings
             :
             : -C create XATTR_PAX with most secure setting
             : -c create XATTR_PAX all default settings
             : -F copy PT_PAX to XATTR_PAX
             : -f copy XATTR_PAX to PT_PAX
             : -L set only PT_PAX flags
             : -l set only XATTR_PAX flags
             :
             : -v view the flags, along with any accompanying operation
             : -h print out this help
  
Note         :  If both enabling and disabling flags are set, the default - is used

The following is an example of paxctl-ng in action:

View both PT_PAX and XATTR_PAX fields (-v):

root # paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : Pem--
	XATTR_PAX: Pem--

Set default '-' for PAGEEXEC (-Pp) for XATTR_FLAGS only (-l) and report the result (-v):

root # paxctl-ng -lPpv /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : Pem--
	XATTR_PAX: -em--

Delete the XATTR_PAX field altogether (-d) and report the result (-v):

root # paxctl-ng -dv /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : Pem--
	XATTR_PAX: not found

Set "em" flags (-em) for XATTR_FLAGS only (-l) and report the result (-v):

root # paxctl-ng -lemv /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : Pem--
	XATTR_PAX: -em--

Copy the XATTR_PAX to PT_PAX flags, overwriting the latter (-f) and report the result (-v):

root # paxctl-ng -fv /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : -em--
	XATTR_PAX: -em--

Silently delete the XATTR_PAX field (-d but no -v):

root # paxctl-ng -d /usr/bin/python3.2

View both PT_PAX and XATTR_PAX fields (-v):

root # paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX   : -em--
	XATTR_PAX: not found

4. Python module, pax.so , and a simple Python frontend, pypaxctl.

We also provide bindings to python via a module, pax.so, which is installed by emerging dev-python/pypax. This package is a dependency of sys-apps/elfix since the both revdep-pax and migrate-pax import it. It can be compiled with either PT_PAX and/or XATTR_PAX support, like paxctl-ng, but it is not as featureful since its scope is limited to just the needs of revdep-pax and migrate-pax. This may change in the future if there is a need to better integrate PaX marking with portage which is written in python.

Currently pax.so publicly exports the following:

pax.setstrflags(str_flags): This function will set both PT_PAX and XATTR_PAX flags to the same value, whenever possible. The flags are specified as a string of the following chars: PpEeMmRrSs. If both the enable and disable flags are given for a particular protection, then the default '-' is used. pax.setbinflags(bin_flags): This function is the same as pax.setstrflags but it takes the flags as a bitwise OR of the binary representation of the flags. The PT_PAX field is stored as this way, while XATTR_PAX is stored as a string of chars PpEeMmRrSs. pax.getflags(elf): This function returns the PaX flags as a tuple of both forms (str_flags, bin_flags), ie., both as a string and its equivalent binary representation are returned. If both PT_PAX and XATTR_PAX are set, then the XATTR_PAX flags will override the PT_PAX flags. pax.deletextpax(elf): This function will delete the XATTR_PAX field completely. It does not touch the PT_PAX field, which cannot be deleted (easily!). pax.PaxError: This exception is thrown whenever getting or setting the flags fails, or when deleting the XATTR_PAX field fails.

pypaxctl is a simple front end to pax.so which just gets and sets the PaX flags using the same logic. When getting the flags, if both PT_PAX and XATTR_PAX are present, the latter will override the former. When setting, it will set both fields whenever possible. Here it is in action:

Retrieve either PT_PAX or XATTR_PAX. The latter has priority if it exists. The canonical order is PEMRS.

root # pypaxctl -g /usr/bin/python3.2
-em--

It turns out that XATTR_PAX didn't exist, so we got PT_PAX.

root # paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: not found

Set some XATTR_PAX flags:

root # paxctl-ng -lPMEv /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: PEM--

Now its reporting XATTR_PAX flags:

root # pypaxctl -g /usr/bin/python3.2
PEM--

Set "me" on both PT_PAX and XATTR_PAX:

root # pypaxctl -s me /usr/bin/python3.2
# paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: Pem--

But what if we want PAGEEXEC off? Then set Pp for the default '-':

root # pypaxctl -s Pp /usr/bin/python3.2
root #
paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: -em--

If the logic of XATTR_PAX taking precedence over PT_PAX is not what you want, it can be compiled with just PT_PAX xor XATTR_PAX support. In this case, the other field is not ever touched, as demonstrated below:

root # paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: PEM--
root # pypaxctl -g /usr/bin/python3.2
-em--
root # pypaxctl -s p /usr/bin/python3.2
root #
paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: pem--
	XT_PAX: PEM--
root # pypaxctl -s PpEem /usr/bin/python3.2
root #
paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: --m--
	XT_PAX: PEM--

5. revdep-pax

This utility is used to map out the linkings between all the ELF objects on your system and their shared objects in both directions. It can then search for PaX flag markings that are mismatched between the shared objects than the executables; and optionally, allows the user to migrate the markings forwards or backwards on a per ELF object basis. Here's a synopsis of its usage:

user $ revdep-pax -h
Package Name : elfix
Bug Reports  : http://bugs.gentoo.org/
Program Name : revdep-pax
Description  : Get or set pax flags on an ELF object
  
Usage        : revdep-pax -f [-v]             print out all forward mappings for all system binaries
             : revdep-pax -r [-ve]            print out all reverse mappings for all system sonames
             : revdep-pax -b OBJECT  [-myv]   print all forward mappings only for OBJECT
             : revdep-pax -s SONAME  [-myve]  print all reverse mappings only for SONAME
             : revdep-pax -l LIBRARY [-myve]  print all reverse mappings only for LIBRARY file
             : revdep-pax [-h]                print out this help
             : -v                             verbose, otherwise just print mismatching objects
             : -e                             only print out executables in shell $PATH
             : -m                             don't just report, but mark the mismatching objects
             : -y                             assume "yes" to all prompts for marking (USE CAREFULLY!)

Here's revdep-pax in action. Since the out is long, we've replaced some of it with ellipses:

Report all mismatching forward linkings:

root # revdep-pax -f
          .....
/usr/bin/python3.2 ( --m-- )
  
	libpython3.2.so.1.0	/usr/lib64/libpython3.2.so.1.0 ( -e--- )
	libpthread.so.0	/lib64/libpthread-2.16.so ( -e--- )
	libc.so.6	/lib64/libc-2.16.so ( -e--- )
	libdl.so.2	/lib64/libdl-2.16.so ( -e--- )
	libutil.so.1	/lib64/libutil-2.16.so ( -e--- )
	libm.so.6	/lib64/libm-2.16.so ( -e--- )
          .....

Forward port PaX flags for python3.2 only:

root # revdep-pax -m -b /usr/bin/python3.2
/usr/bin/python3.2 (--m--)
  
	libpython3.2.so.1.0	/usr/lib64/libpython3.2.so.1.0 ( -e--- )
	libpthread.so.0	/lib64/libpthread-2.16.so ( -e--- )
	libc.so.6	/lib64/libc-2.16.so ( -e--- )
	libdl.so.2	/lib64/libdl-2.16.so ( -e--- )
	libutil.so.1	/lib64/libutil-2.16.so ( -e--- )
	libm.so.6	/lib64/libm-2.16.so ( -e--- )
  
	Will mark libraries with --m--
  
	Set flags for /usr/lib64/libpython3.2.so.1.0 (y/n): n		< --- You will be prompted unless you give -y.
	Set flags for /lib64/libpthread-2.16.so (y/n): n		< --- We'll say 'n' to each for this demo.
	Set flags for /lib64/libc-2.16.so (y/n): n
	Set flags for /lib64/libdl-2.16.so (y/n): n
	Set flags for /lib64/libutil-2.16.so (y/n): n
	Set flags for /lib64/libm-2.16.so (y/n): n

Report all mismatching reverse linkings:

root # revdep-pax -r
          .....
libpython3.2.so.1.0	/usr/lib64/libpython3.2.so.1.0 ( -e--- )	< --- The format is soname /path/to/its/elf_object (flags).
  
	/usr/bin/python3.2 ( --m-- )					< --- There is a mismatch here as expected
          .....										from the previous step.

Let's migrate from the library's flags to the executable using the soname (-s). We could also have used /usr/lib64/libpython3.2.so.1.0 with the -l flag.

root # revdep-pax -m -s libpython3.2.so.1.0
libpython3.2.so.1.0	/usr/lib64/libpython3.2.so.1.0 (-e---)
  
	/usr/bin/python3.2 ( --m-- )
  
	Will mark binaries with -e---
  
	Set flags for /usr/bin/python3.2 (y/n): y			< --- Confirm 'y' we want to do this.
  
		/usr/bin/python3.2 ( -em-- )
root # paxctl-ng -v /usr/bin/python3.2
/usr/bin/python3.2:
	PT_PAX: -em--
	XT_PAX: -em--

6. migrate-pax

At this point you're probably fed up with dealing with both PT_PAX and XATTR_PAX fields and their relationship to the kernel's configuration, and you just want to drop the older PT_PAX and get on with life! migrate-pax does only that ... it will go through all ELF objects on your system and migrate the PT_PAX field to XATTR_PAX. For more details on how to migrate, see our guide on migrating PaX flags from PT_PAX to XATTR_PAX .

user $ migrate-pax -h
Package Name : elfix
Bug Reports  : http://bugs.gentoo.org/
Program Name : migrate
Description  : Migrate PT_PAX to XATTR_PAX Flags on all system ELF objects
  
Usage        : migrate -v        print out all system ELF objects
             : migrate -m [-v]   migrate flags on all system ELF objects
             : migrate -d [-v]   delete XATTR_PAX on all system ELF objects
             : migrate [-h]      print out this help
             : -v                be verbose when migrating

Acknowledgements

We would like to thank the following authors and editors for their contributions to this guide:

  • Anthony G. Basile
  • Francisco Izquierdo
  • Brandon Hale
  • blackace
  • solar