Position-Independent-Executable is a feature of Binutils, Libc, and
GCC that creates an executable which is something between a shared
library and a normal executable. Programs compiled with these
features appear as “shared
object” with the file(1) command. This allows the
executable to behave like a shared library so base addresses can be
relocatable. The PIE program must be linked to Scrt1.o. Scrt1.o is
available from the newer versions of Libc. Furthermore these programs
must be linked with the -pie
ld(1) command from a
Binutils version 2.15 or later. GCC supports this natively with the
-fPIE switch in version 3.4
or later.
When all of the object code is position independent the kernel can disallow text relocation. This dramatically increases the security of the system with little performance loss. PaX and Grsec kernels have this option available though very few systems have been able to take advantage of it. The entire base system can be built position independent with the exception of the Grub boot loader, and Glibc's utilities due to non-pic assembly code. These programs will still function if they are dynamically linked. Other exceptions are X11 windowing system, Mplayer, and a few other graphical programs which were not programed with PIE in mind, this should come in time. Gzip uses assembly code which is not position independent, but this can be omitted at compile time and Gzip will use only C code.
PaX can also randomize the return addresses of PIE programs with Address Space Layout Randomization (ASLR). This can prevent security bugs from being taken advantage of by attackers.
You can search for text relocation in programs with the following command:
readelf -d /path/to/object | grep TEXTREL
It is possible for TEXTREL to be present in both executable programs and libraries. Further debugging is needed to find the specific code that is not position independent, it is most often assembly. If a program errors at compile time with 'ASM' and 'BREG' in the message, this is non-pic assembly.
The coreutils uname patch from LFS also uses assembly code which is not position independent.
The man page for ld has
a description for -pie. See
man 1 ld.
Use the NOELFRELOCS in PaX or Grsec
kernel options to disable text relocation.
The fPIE flag can only be
passed to executables, not libraries. The fPIE flag gives some advantages over
fPIC in that the compiler can
assume the code will stay local to the program. This translates into
optimizations having a greater effect; non-static functions can be
inlined at -O3, etc. The
hardened-specs used in the book adds filters to the GCC link_command spec to distinguish
executables from libraries, so the ld -pie switch is only passed when linking
executables. The same filters can not be used for cc1, so the cc1 spec passes -fPIC instead of -fPIE to everything unless the
-static or -no-pie flags are used. Using
gcc -fPIC with
ld -pie works fairly
well, all the PaX/Grsec kernel features will be able to have full
advantages. fPIE is known to
cause text relocation in some programs, so it must be used with care.
In this book we patch some programs, and use sed(1) commands on others, to add
gcc -pie -fpie on
program executables. fPIE
must be added surgically, and not to environment cflags. The
hardened-specs preserves the vanilla gcc -pie behaviour, meaning if you
use gcc -pie neither
-fpic nor -fpie will be automatically added, so
both -pie -fpie must be used
together (as per the gcc man page). gcc -pie affects which startfiles
are used (Scrt.o), so it must be used
in conjuction with ld
-pie. Almost all packages use GCC to do linking, so
setting environment ldflags is almost never needed.
Beyond the packages in this book the hardened-specs will work
perfectly fine with -fPIC. If
you wish to use -fPIE to have
greater optimization be sure to use readelf -d to check for TEXTREL. If
-fPIE is passed to one object
in a library it will cause a TEXTREL section in that library, and it
will not work correctly. Libraries, private or otherwise, need to be
compiled with -fPIC.
On x86 systems -fPIC and
-fpic are exactly the same.
Ditto with -fPIE and
-fpie.
See also: