[[!meta title="Hardening pkgsrc"]]
A number of mechanisms are available in
[pkgsrc](https://www.pkgsrc.org/) to improve the security of the
resulting system. This page describes the mechanisms, and gives hints
about detecting and fixing problems.
# Mechanisms
Mechanisms can be enabled individually in `mk.conf`, and are
individually described below. They are sorted by whether they are
enabled by default, and then by their ordering in `mk/defaults/mk.conf`.
Typically, a feature will cause some programs to fail to build or work
when first enabled. This can be due to latent problems in the
program, and can be due to other reasons. After enough testing to
have confidence that user problems will be quite rare, individual
mechanisms will be enabled by default.
For each mechanism, see the Caveats section below for an explanation
of what might go wrong at compile time and at run time, and how to
notice and address these problems.
## Enabled by default in the stable branch
### PKGSRC_USE_FORTIFY
This allows substitute wrappers to be used for some commonly used
library functions that do not have built-in bounds checking - but
could in some cases.
TODO: Explain FORTIFY_SOURCE 1 vs 2, and which is used. Give a link
to a good explanation of the technique. Explain if this is gcc specific.
It has been enabled by default since pkgsrc-2017Q3.
### PKGSRC_USE_SSP
This enables a stack-smashing protection mitigation. It is done by adding a
guard variable to functions with vulnerable objects. The guards are initialized
when a function is entered and then checked when the function exits. The guard
check will fail and the program forcibly exited if the variable was modified in
the meantime. This can happen in case of buffer overflows or memory corruption,
and therefore exposing these bugs.
Different mitigation levels are available:
* the default ("yes"), which will only protect functions considered vulnerable
by the compiler;
* "all", which will protect every function;
* "strong", which will apply a better balance between the two settings above.
This mitigation is supported by both GCC and clang. It may be supported in
additional compilers, possibly under a different name. It is particularly useful
for unsafe programming languages, such as C/C++.
It is enabled by default where known supported since pkgsrc-2017Q3.
* <https://en.wikipedia.org/wiki/Buffer_overflow_protection>
## Enabled by default in pkgsrc HEAD
## Not enabled by default
### PKGSRC_MKPIE
This requests the the creation of PIE (Position Independent
Executables) for all executables. The PIE mechanism is normally used
for shared libraries so that they can be loaded at differing addresses
at runtime. PIE itself does not have useful security properties.
However, some operating systems support Address Space Layout
Randomization (ASLR), which causes different addresses to be used each
time a program is run. This makes it more difficult for an attacker
to guess addresses and thus makes exploits harder to construct.
PIE executables will only be built for toolchains that are known to support PIE.
Currently, this means NetBSD on amd64 and i386.
### PKGSRC_USE_RELRO
This also makes the exploitation of some security vulnerabilities more
difficult in some cases.
TODO: Explain gcc vs clang, and whether this has broad support or just
a few platforms.
TODO: Address "partial" vs "full"; which is this?
TODO: Give a link to a comprehensive explanation.
### PKGSRC_USE_STACK_CHECK
This uses `-fstack-check` with GCC for another stack protection
mitigation.
# Caveats
## Problems with `PKGSRC_MKPIE`
### Recent support for cwrappers
`PKGSRC_MKPIE` is only supported by `pkgtools/cwrappers` from the 2017Q3
release on (`USE_CWRAPPERS` in `mk.conf`).
### Packages failing to build
A number of packages may fail to build with this option enabled. The failures
are often related to the absence of the `-fPIC` compilation flag when building
libraries or executables (or ideally `-fPIE` in the latter case). This flag is
added to the `CFLAGS` already, but requires the package to actually support it.
#### How to fix
These instructions are meant as a reference only; they likely need to be adapted
for many packages individually.
For packages using `Makefiles`:
MAKE_FLAGS+= CFLAGS=${CFLAGS:Q}
MAKE_FLAGS+= LDFLAGS=${LDFLAGS:Q}
For packages using `Imakefiles`:
MAKE_FLAGS+= CCOPTIONS=${CFLAGS:Q}
MAKE_FLAGS+= LOCAL_LDFLAGS=${LDFLAGS:Q}
### Run-time crashes
Some programs may fail to run, or crash at random times once built as PIE. Two
scenarios are essentially possible:
* actual bug in the program crashing, exposed thanks to ASLR/mprotect;
* bug in the implementation of ASLR/mprotect in the Operating System.
## Problems with `PKGSRC_USE_FORTIFY`
### Packages failing to build
This feature makes use of pre-processing directives to look for hardened,
alternative implementations of essential library calls. Some programs may fail
to build as a result; this usually happens for those trying too hard to be
portable, or otherwise abusing definitions in the standard library.
This will require a modification to the program, or disabling this feature for
part or all of the build.
### Run-time crashes
Just like with `PKGSRC_MKPIE` above, this feature may cause some programs to
crash, usually indicating an actual bug in the program. The fix will typically
involve patching the original program.
### Optimization is required
At least in the case of GCC, FORTIFY will only be applied if optimization is
applied while compiling. This means that the CFLAGS should also contain -O, -O2
or another optimization level. This cannot easily be applied globally, as some
packages may require specific optimization levels.
## Problems with `PKGSRC_USE_RELRO`
### Performance impact
For better protection, full RELRO requires every symbol to be resolved when the
program starts, rather than simply when required at run-time. This will have
more impact on programs using a lot of symbols, or linked to libraries exposing
a lot of symbols. Therefore, daemons or programs otherwise running in
background are affected only when started. Programs loading plug-ins at
run-time are affected when loading the plug-ins.
The impact is not expected to be noticeable on modern hardware, except in some
cases for big programs.
### Run-time crashes
Some programs handle plug-ins and dependencies in a way that conflicts with
RELRO: for instance, with an initialization routine listing any other plug-in
required. With full RELRO, the missing symbols are resolved before the
initialization routine can run, and the dynamic loader will not be able to find
them directly and abort as a result. Unfortunately, this is how Xorg loads its
drivers. Partial RELRO can be applied instead in this case.
## Problems with `PKGSRC_USE_SSP`
### Packages failing to build
The stack-smashing protection provided by this option does not work for some
programs. The two most common situations in which this happens are:
* the program makes use of the `alloca(3)` library call (memory allocator on the
stack)
* the program allocates variables on the stack, with the size determined at
run-time.
Both cases will require a modification to the program, or disabling this feature
for part or all of the build.
### Run-time crashes
Again, this feature may cause some programs to crash, usually indicating an
actual bug in the program. Patching the original program is then required.
### Performance impact
The compiler emits extra code when using this feature: a check for buffer
overflows is performed when entering and exiting functions, requiring an extra
variable on the stack. The level of protection can otherwise be adjusted to
affect only those functions considered more sensitive by the compiler (with
`-fstack-protector` instead of `-fstack-protector-all`).
The impact is not expected to be noticeable on modern hardware. However,
programs with a hard requirement to run at the fastest possible speed should
avoid using this feature, or using libraries built with this feature.
# Auditing the system
The illusion of security is worse than having no security at all. This section
lists a number of ways to ensure the security features requested are actually
effective.
_These instructions were obtained and tested on a system derived from NetBSD 7
(amd64). YMMV._
## Checking for PIE
The ELF executable type in use changes for binaries built as PIE; without:
$ file /path/to/bin/ary
/path/to/bin/ary: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for NetBSD 7.0, not stripped
as opposed to the following binary, built as PIE:
$ file /path/to/pie/bin/ary
/path/to/pie/bin/ary: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for NetBSD 7.0, not stripped
The latter result is then what is expected.
## Checking for partial RELRO
The following command should list a section called `RELRO`:
$ objdump -p /path/to/bin/ary
/path/to/bin/ary: file format elf64-x86-64
Program Header:
[...]
RELRO off 0x0000000000000d78 vaddr 0x0000000000600d78 paddr 0x0000000000600d78 align 2**0
This check is now performed automatically if `PKG_DEVELOPER` is set and `RELRO`
is enabled.
## Checking for full RELRO
The dynamic loader will apply RELRO immediately when detecting the presence of
the `BIND_NOW` flag:
$ objdump -x /path/to/bin/ary
/path/to/bin/ary: file format elf64-x86-64
Dynamic Section:
[...]
BIND_NOW 0x0000000000000000
This has to be combined with partial RELRO (see above) to be fully efficient.
## Checking for SSP
Building objects, binaries and libraries with SSP will affect the presence of
additional symbols in the resulting file:
$ nm /path/to/bin/ary
[...]
U __stack_chk_fail
0000000000600ea0 B __stack_chk_guard
This is an indicator that the program was indeed built with support for SSP.
# References
* <http://tk-blog.blogspot.co.at/2009/02/relro-not-so-well-known-memory.html>
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb