Hardening Psi

Most Linux distributions started using hardening compiler and linker options for the programs in their packaging systems. Due to the slightly unorthodox build strategy of Psi (and even worse Psi+), it is not absolutely trivial to add these options when building it. Following is a short of instructions to build Psi (would also work for Psi+) with several hardening options.

The options I will be using for this (feel free to use your own), are:

  1. -fPIE and -pie to make Psi a Position Independent Executable, so the kernel can relocate the internal symbols of the application as part of its Address Space Layout Randomization (ASLR).
  2. -fstack-protector-strong which will add stack canaries for stack smashing protection.
  3. -D_FORTIFY_SOURCE=2 as compile-time protection against buffer overflows.
  4. -z,relro makes part of the Global Offset Table (GOT) read-only before glibc’s runtime liker hands control over to the executable.
  5. -z,now forces a binding of all dynamic symbols on application startup. The runtime linker can then make the whole GOT read-only. Note that this might incurs some minor performance penalty on initial program startup (but makes the first symbol lookup ever so slighty quicker…), all of that should not matter for Psi. Since we don’t want to hard-code these options into Psi, I created a patch to make Psi use the regular $CFLAGS, $CXXFLAGS and $LDFLAGS. If there is a Qter way of doing this, please let me know.

After this we can set the flags:

export LDFLAGS="-pie -z,relro -z,now"
export CFLAGS="-D_FORTIFY_SOURCE=2 -fstack-protector-strong -fPIE -pie"
export CXXFLAGS="$CFLAGS"

Now we are ready to build Psi, so do the regular ./configure && make dance.

After a while the build should be done and a ready to use psi executable should be in the build directory. As it is now a PIE, the file command should not be able to identify it as executable, but will call it a “shared object with intrepreter” which sounds executable enough to me. ;-)

After starting the executable you can use very nice checksec (might be included in your distribution) to make sure everything worked as planned. When invoked as checksec -p psi you should something similar to the following output:

COMMAND  RELRO           STACK CANARY            SECCOMP          NX/PaX        PIE                     FORTIFY
psi                Partial RELRO   Canary found                 No Seccomp       NX enabled    PIE enabled             Yes

Which is already a big improvement to your previous Psi builds or what is bundled with your distribution (at least with Fedora).