1: [[!meta title="Hardening pkgsrc"]]
2:
3: A number of mechanisms are available in
4: [pkgsrc](https://www.pkgsrc.org/) to improve the security of the
5: resulting system. This page describes the mechanisms, and gives hints
6: about detecting and fixing problems.
7:
8: # Mechanisms
9:
10: Mechanisms can be enabled individually in `mk.conf`, and are
11: individually described below. They are sorted by whether they are
12: enabled by default, and then by their ordering in `mk/defaults/mk.conf`.
13:
14: Typically, a feature will cause some programs to fail to build or work
15: when first enabled. This can be due to latent problems in the
16: program, and can be due to other reasons. After enough testing to
17: have confidence that user problems will be quite rare, individual
18: mechanisms will be enabled by default.
19:
20: For each mechanism, see the Caveats section below for an explanation
21: of what might go wrong at compile time and at run time, and how to
22: notice and address these problems.
23:
24: ## Enabled by default
25:
26: ### PKGSRC_USE_FORTIFY
27:
28: This allows substitute wrappers to be used for some commonly used
29: library functions that do not have built-in bounds checking - but
30: could in some cases.
31:
32: Two mitigation levels are available:
33:
34: - "weak" only enables checks at compile-time.
35: - "strong" enables checks at compile-time and runtime.
36:
37: `strong` has been enabled by default since pkgsrc-2017Q3.
38:
39: ### PKGSRC_USE_SSP
40:
41: This enables a stack-smashing protection mitigation. It is done by adding a
42: guard variable to functions with vulnerable objects. The guards are initialized
43: when a function is entered and then checked when the function exits. The guard
44: check will fail and the program forcibly exited if the variable was modified in
45: the meantime. This can happen in case of buffer overflows or memory corruption,
46: and therefore exposing these bugs.
47:
48: Different mitigation levels are available:
49:
50: * "yes", which will only protect functions considered vulnerable
51: by the compiler;
52: * "all", which will protect every function;
53: * "strong", the default, which will apply a better balance between the two settings above.
54:
55: This mitigation is supported by both GCC and clang. It may be supported in
56: additional compilers, possibly under a different name. It is particularly useful
57: for unsafe programming languages, such as C/C++.
58:
59: "yes" is enabled by default where known supported since pkgsrc-2017Q3.
60: "strong" is enabled by default where known supported since pkgsrc-2021Q4.
61:
62: More details can be found here:
63:
64: * <https://en.wikipedia.org/wiki/Buffer_overflow_protection>
65:
66: ### PKGSRC_MKPIE
67:
68: This requests the creation of PIE (Position Independent Executables) for all
69: executables. The PIE mechanism is normally used for shared libraries, so that
70: they can be loaded at differing addresses at runtime. PIE itself does not have
71: useful security properties; however, it is necessary to fully leverage some,
72: such as ASLR. Some operating systems support Address Space Layout Randomization
73: (ASLR), which causes different addresses to be used each time a program is run.
74: This makes it more difficult for an attacker to guess addresses and thus makes
75: exploits harder to construct. With PIE, ASLR can really be applied to the entire
76: program, instead of the stack and heap only.
77:
78: PIE executables will only be built for toolchains that are known to support PIE.
79: Currently, this means NetBSD on x86, ARM, SPARC64, m68k, and MIPS.
80:
81: PKGSRC_MKPIE was enabled by default after the pkgsrc-2021Q3 branch.
82:
83:
84: ### PKGSRC_USE_RELRO
85:
86: This also makes the exploitation of some security vulnerabilities more
87: difficult in some cases.
88:
89: Two different mitigation levels are available:
90:
91: * partial: the ELF sections are reordered so that internal data sections
92: precede the program's own data sections, and non-PLT GOT is read-only;
93: * full: in addition to partial RELRO, every relocation is performed immediately
94: when starting the program (with a slight performance impact), allowing the
95: entire GOT to be read-only.
96:
97: This is currently supported by GCC. Many software distributions now enable this
98: feature by default, at the "partial" level.
99:
100: More details can be found here:
101:
102: * <https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro>
103: * <http://tk-blog.blogspot.co.at/2009/02/relro-not-so-well-known-memory.html>
104:
105: ## Not enabled by default
106:
107: ### PKGSRC_MKREPRO
108:
109: With this option, pkgsrc will try to build packages reproducibly. This allows
110: packages built from the same tree and with the same options, to produce
111: identical results bit by bit. This option should be combined with ASLR and
112: `PKGSRC_MKPIE` to avoid predictable address offsets for attackers attempting to
113: exploit security vulnerabilities.
114:
115: More details can be found here:
116:
117: * <https://reproducible-builds.org/>
118:
119: More work likely needs to be done before pkgsrc is fully reproducible.
120:
121: ### PKGSRC_USE_STACK_CHECK
122:
123: This uses `-fstack-check` with GCC for another stack protection mitigation.
124:
125: It asks the compiler to generate code verifying that it does not corrupt the
126: stack. According to GCC's manual page, this is really only useful for
127: multi-threaded programs.
128:
129: # Caveats
130:
131: ## Problems with `PKGSRC_MKPIE`
132:
133: ### Packages failing to build
134:
135: A number of packages may fail to build with this option enabled. The failures
136: are often related to the absence of the `-fPIC` compilation flag when building
137: libraries or executables (or ideally `-fPIE` in the latter case). This flag is
138: added to the `CFLAGS` already, but requires the package to actually support it.
139:
140: #### How to fix
141:
142: These instructions are meant as a reference only; they likely need to be adapted
143: for many packages individually.
144:
145: For packages using `Makefiles`:
146:
147: MAKE_FLAGS+= CFLAGS=${CFLAGS:Q}
148: MAKE_FLAGS+= LDFLAGS=${LDFLAGS:Q}
149:
150: For packages using `Imakefiles`:
151:
152: MAKE_FLAGS+= CCOPTIONS=${CFLAGS:Q}
153: MAKE_FLAGS+= LOCAL_LDFLAGS=${LDFLAGS:Q}
154:
155: ### Run-time crashes
156:
157: Some programs may fail to run, or crash at random times once built as PIE. Two
158: scenarios are essentially possible. This is nearly always due to a bug in
159: the program being exposed due to ASLR.
160:
161: ### Disabling PKGSRC_MKPIE on a per-package basis
162:
163: Ideally, packages should be fixed for compatibility with MKPIE.
164: However, in some cases this is very difficult, due to complex build systems,
165: packages using non-standard toolchains, or programming languages with odd
166: bootstrapping mechanisms.
167:
168: To disable `PKGSRC_MKPIE` on a per-package basis, set `MKPIE_SUPPORTED= no` in the package's Makefile before `bsd.prefs.mk` is included.
169:
170: ## Problems with `PKGSRC_USE_FORTIFY`
171:
172: ### Packages failing to build
173:
174: This feature makes use of pre-processing directives to look for hardened,
175: alternative implementations of essential library calls. Some programs may fail
176: to build as a result; this usually happens for those trying too hard to be
177: portable, or otherwise abusing definitions in the standard library.
178:
179: This will require a modification to the program, or disabling this feature
180: by adding in the package `Makefile`:
181:
182: FORTIFY_SUPPORTED= no
183:
184: ### Run-time crashes
185:
186: Just like with `PKGSRC_MKPIE` above, this feature may cause some programs to
187: crash, usually indicating an actual bug in the program. The fix will typically
188: involve patching the original program.
189:
190: ### Optimization is required
191:
192: At least in the case of GCC, FORTIFY will only be applied if optimization is
193: applied while compiling. This means that the CFLAGS should also contain -O, -O2
194: or another optimization level. This cannot easily be applied globally, as some
195: packages may require specific optimization levels.
196:
197: ## Problems with `PKGSRC_USE_RELRO`
198:
199: ### Performance impact
200:
201: For better protection, full RELRO requires every symbol to be resolved when the
202: program starts, rather than simply when required at run-time. This will have
203: more impact on programs using a lot of symbols, or linked to libraries exposing
204: a lot of symbols. Therefore, daemons or programs otherwise running in
205: background are affected only when started. Programs loading plug-ins at
206: run-time are affected when loading the plug-ins.
207:
208: The impact is not expected to be noticeable on modern hardware, except in some
209: cases for big programs.
210:
211: ### Run-time crashes
212:
213: Some programs handle plug-ins and dependencies in a way that conflicts with
214: RELRO: for instance, with an initialization routine listing any other plug-in
215: required. With full RELRO, the missing symbols are resolved before the
216: initialization routine can run, and the dynamic loader will not be able to find
217: them directly and abort as a result. Unfortunately, this is how Xorg loads its
218: drivers. Partial RELRO can be applied instead in this case.
219:
220: ### Disabling RELRO on a per-package basis
221:
222: To disable RELRO on a per-package basis, set `RELRO_SUPPORTED= no` in the package's Makefile before `bsd.prefs.mk` is included.
223:
224: ## Problems with `PKGSRC_USE_SSP`
225:
226: ### Packages failing to build
227:
228: The stack-smashing protection provided by this option does not work for some
229: programs. The most common situation in which this happens is when the program
230: allocates variables on the stack, with the size determined at run-time.
231:
232: Both cases will require a modification to the program, or disabling this feature
233: by adding in the package `Makefile`:
234:
235: SSP_SUPPORTED= no
236:
237: ### Run-time crashes
238:
239: Again, this feature may cause some programs to crash via a SIGABRT,
240: usually indicating an actual bug in the program.
241:
242: On NetBSD `LOG_CRIT` level `syslog()` messages are sent and - by
243: default - appended to `/var/log/messages`, e.g.:
244:
245: Jan 6 15:42:51 <hostname> -: <hostname> <program> - - - buffer overflow detected; terminated
246:
247: (where `<hostname>` is the `hostname(1)` and `<program>` is the
248: `basename(1)` of the program crashed).
249:
250: Patching the original program is then required.
251:
252: Rebuilding the package via:
253:
254: % env CFLAGS=-g INSTALL_UNSTRIPPED=yes make replace
255:
256: and inspecting the `backtrace` of the coredump via the debugger
257: should point out the problematic call by inspecting the frame
258: calling the `_chk()' (SSP) function.
259:
260: ### Performance impact
261:
262: The compiler emits extra code when using this feature: a check for buffer
263: overflows is performed when entering and exiting functions, requiring an extra
264: variable on the stack. The level of protection can otherwise be adjusted to
265: affect only those functions considered more sensitive by the compiler (with
266: `-fstack-protector` instead of `-fstack-protector-all`).
267:
268: The impact is not expected to be noticeable on modern hardware. However,
269: programs with a hard requirement to run at the fastest possible speed should
270: avoid using this feature, or using libraries built with this feature.
271:
272: # Auditing the system
273:
274: The illusion of security is worse than having no security at all. This section
275: lists a number of ways to ensure the security features requested are actually
276: effective.
277:
278: _These instructions were obtained and tested on a system derived from NetBSD 7
279: (amd64). YMMV._
280:
281: ## Checking for PIE
282:
283: The ELF executable type in use changes for binaries built as PIE; without:
284:
285: $ file /path/to/bin/ary
286: /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
287:
288: as opposed to the following binary, built as PIE:
289:
290: $ file /path/to/pie/bin/ary
291: /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
292:
293: The latter result is then what is expected.
294:
295: ## Checking for partial RELRO
296:
297: The following command should list a section called `RELRO`:
298:
299: $ objdump -p /path/to/bin/ary
300:
301: /path/to/bin/ary: file format elf64-x86-64
302:
303: Program Header:
304: [...]
305: RELRO off 0x0000000000000d78 vaddr 0x0000000000600d78 paddr 0x0000000000600d78 align 2**0
306:
307: This check is now performed automatically if `PKG_DEVELOPER` is set and `RELRO`
308: is enabled.
309:
310: ## Checking for full RELRO
311:
312: The dynamic loader will apply RELRO immediately when detecting the presence of
313: the `BIND_NOW` flag:
314:
315: $ objdump -x /path/to/bin/ary
316:
317: /path/to/bin/ary: file format elf64-x86-64
318:
319: Dynamic Section:
320: [...]
321: BIND_NOW 0x0000000000000000
322:
323: This has to be combined with partial RELRO (see above) to be fully efficient.
324:
325: ## Checking for SSP
326:
327: Building objects, binaries and libraries with SSP will affect the presence of
328: additional symbols in the resulting file:
329:
330: $ nm /path/to/bin/ary
331: [...]
332: U __stack_chk_fail
333: 0000000000600ea0 B __stack_chk_guard
334:
335: This is an indicator that the program was indeed built with support for SSP.
336:
337: This check is now performed automatically (where supported) if `PKG_DEVELOPER`
338: is set and `SSP` is enabled.
339:
340: If it is needed to disable SSP check per-package, please add in the package
341: `Makefile`:
342:
343: CHECK_SSP_SUPPORTED= no
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb