File: | Dpkg/Vendor/Debian.pm |
Coverage: | 48.3% |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | # Copyright © 2009-2011 Raphaël Hertzog <hertzog@debian.org> | ||||||
2 | # Copyright © 2009, 2011-2017 Guillem Jover <guillem@debian.org> | ||||||
3 | # | ||||||
4 | # Hardening build flags handling derived from work of: | ||||||
5 | # Copyright © 2009-2011 Kees Cook <kees@debian.org> | ||||||
6 | # Copyright © 2007-2008 Canonical, Ltd. | ||||||
7 | # | ||||||
8 | # This program is free software; you can redistribute it and/or modify | ||||||
9 | # it under the terms of the GNU General Public License as published by | ||||||
10 | # the Free Software Foundation; either version 2 of the License, or | ||||||
11 | # (at your option) any later version. | ||||||
12 | # | ||||||
13 | # This program is distributed in the hope that it will be useful, | ||||||
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
16 | # GNU General Public License for more details. | ||||||
17 | # | ||||||
18 | # You should have received a copy of the GNU General Public License | ||||||
19 | # along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
20 | |||||||
21 | package Dpkg::Vendor::Debian; | ||||||
22 | |||||||
23 | 19 19 19 | 330 12 226 | use strict; | ||||
24 | 19 19 19 | 27 12 446 | use warnings; | ||||
25 | |||||||
26 | our $VERSION = '0.01'; | ||||||
27 | |||||||
28 | 19 19 19 | 37 15 291 | use Dpkg; | ||||
29 | 19 19 19 | 32 13 438 | use Dpkg::Gettext; | ||||
30 | 19 19 19 | 41 11 481 | use Dpkg::ErrorHandling; | ||||
31 | 19 19 19 | 31 17 563 | use Dpkg::Control::Types; | ||||
32 | |||||||
33 | 19 19 19 | 28 11 34 | use parent qw(Dpkg::Vendor::Default); | ||||
34 | |||||||
35 | =encoding utf8 | ||||||
36 | |||||||
37 - 46 | =head1 NAME Dpkg::Vendor::Debian - Debian vendor class =head1 DESCRIPTION This vendor class customizes the behaviour of dpkg scripts for Debian specific behavior and policies. =cut | ||||||
47 | |||||||
48 | sub run_hook { | ||||||
49 | 273 | 1 | 213 | my ($self, $hook, @params) = @_; | |||
50 | |||||||
51 | 273 | 569 | if ($hook eq 'package-keyrings') { | ||||
52 | 0 | 0 | return ('/usr/share/keyrings/debian-keyring.gpg', | ||||
53 | '/usr/share/keyrings/debian-nonupload.gpg', | ||||||
54 | '/usr/share/keyrings/debian-maintainers.gpg'); | ||||||
55 | } elsif ($hook eq 'archive-keyrings') { | ||||||
56 | 0 | 0 | return ('/usr/share/keyrings/debian-archive-keyring.gpg'); | ||||
57 | } elsif ($hook eq 'archive-keyrings-historic') { | ||||||
58 | 0 | 0 | return ('/usr/share/keyrings/debian-archive-removed-keys.gpg'); | ||||
59 | } elsif ($hook eq 'builtin-build-depends') { | ||||||
60 | 0 | 0 | return qw(build-essential:native); | ||||
61 | } elsif ($hook eq 'builtin-build-conflicts') { | ||||||
62 | 0 | 0 | return (); | ||||
63 | } elsif ($hook eq 'register-custom-fields') { | ||||||
64 | } elsif ($hook eq 'extend-patch-header') { | ||||||
65 | 0 | 0 | my ($textref, $ch_info) = @params; | ||||
66 | 0 | 0 | if ($ch_info->{'Closes'}) { | ||||
67 | 0 | 0 | foreach my $bug (split(/\s+/, $ch_info->{'Closes'})) { | ||||
68 | 0 | 0 | $$textref .= "Bug-Debian: https://bugs.debian.org/$bug\n"; | ||||
69 | } | ||||||
70 | } | ||||||
71 | |||||||
72 | # XXX: Layer violation... | ||||||
73 | 0 | 0 | require Dpkg::Vendor::Ubuntu; | ||||
74 | 0 | 0 | my $b = Dpkg::Vendor::Ubuntu::find_launchpad_closes($ch_info->{'Changes'}); | ||||
75 | 0 | 0 | foreach my $bug (@$b) { | ||||
76 | 0 | 0 | $$textref .= "Bug-Ubuntu: https://bugs.launchpad.net/bugs/$bug\n"; | ||||
77 | } | ||||||
78 | } elsif ($hook eq 'update-buildflags') { | ||||||
79 | 4 | 4 | $self->_add_build_flags(@params); | ||||
80 | } elsif ($hook eq 'builtin-system-build-paths') { | ||||||
81 | 0 | 0 | return qw(/build/); | ||||
82 | } elsif ($hook eq 'build-tainted-by') { | ||||||
83 | 0 | 0 | return $self->_build_tainted_by(); | ||||
84 | } elsif ($hook eq 'sanitize-environment') { | ||||||
85 | # Reset umask to a sane default. | ||||||
86 | 0 | 0 | umask 0022; | ||||
87 | # Reset locale to a sane default. | ||||||
88 | 0 | 0 | $ENV{LC_COLLATE} = 'C.UTF-8'; | ||||
89 | } elsif ($hook eq 'backport-version-regex') { | ||||||
90 | 4 | 9 | return qr/~(bpo|deb)/; | ||||
91 | } else { | ||||||
92 | 250 | 229 | return $self->SUPER::run_hook($hook, @params); | ||||
93 | } | ||||||
94 | } | ||||||
95 | |||||||
96 | sub _add_build_flags { | ||||||
97 | 4 | 4 | my ($self, $flags) = @_; | ||||
98 | |||||||
99 | # Default feature states. | ||||||
100 | 4 | 17 | my %use_feature = ( | ||||
101 | future => { | ||||||
102 | lfs => 0, | ||||||
103 | }, | ||||||
104 | qa => { | ||||||
105 | bug => 0, | ||||||
106 | canary => 0, | ||||||
107 | }, | ||||||
108 | reproducible => { | ||||||
109 | timeless => 1, | ||||||
110 | fixfilepath => 1, | ||||||
111 | fixdebugpath => 1, | ||||||
112 | }, | ||||||
113 | optimize => { | ||||||
114 | lto => 0, | ||||||
115 | }, | ||||||
116 | sanitize => { | ||||||
117 | address => 0, | ||||||
118 | thread => 0, | ||||||
119 | leak => 0, | ||||||
120 | undefined => 0, | ||||||
121 | }, | ||||||
122 | hardening => { | ||||||
123 | # XXX: This is set to undef so that we can cope with the brokenness | ||||||
124 | # of gcc managing this feature builtin. | ||||||
125 | pie => undef, | ||||||
126 | stackprotector => 1, | ||||||
127 | stackprotectorstrong => 1, | ||||||
128 | fortify => 1, | ||||||
129 | format => 1, | ||||||
130 | relro => 1, | ||||||
131 | bindnow => 0, | ||||||
132 | }, | ||||||
133 | ); | ||||||
134 | |||||||
135 | 4 | 4 | my %builtin_feature = ( | ||||
136 | hardening => { | ||||||
137 | pie => 1, | ||||||
138 | }, | ||||||
139 | ); | ||||||
140 | |||||||
141 | ## Setup | ||||||
142 | |||||||
143 | 4 | 480 | require Dpkg::BuildOptions; | ||||
144 | |||||||
145 | # Adjust features based on user or maintainer's desires. | ||||||
146 | 4 | 8 | my $opts_build = Dpkg::BuildOptions->new(envvar => 'DEB_BUILD_OPTIONS'); | ||||
147 | 4 | 5 | my $opts_maint = Dpkg::BuildOptions->new(envvar => 'DEB_BUILD_MAINT_OPTIONS'); | ||||
148 | |||||||
149 | 4 | 9 | foreach my $area (sort keys %use_feature) { | ||||
150 | 24 | 22 | $opts_build->parse_features($area, $use_feature{$area}); | ||||
151 | 24 | 19 | $opts_maint->parse_features($area, $use_feature{$area}); | ||||
152 | } | ||||||
153 | |||||||
154 | 4 | 499 | require Dpkg::Arch; | ||||
155 | |||||||
156 | 4 | 4 | my $arch = Dpkg::Arch::get_host_arch(); | ||||
157 | 4 | 6 | my ($abi, $libc, $os, $cpu) = Dpkg::Arch::debarch_to_debtuple($arch); | ||||
158 | |||||||
159 | 4 | 21 | unless (defined $abi and defined $libc and defined $os and defined $cpu) { | ||||
160 | 0 | 0 | warning(g_("unknown host architecture '%s'"), $arch); | ||||
161 | 0 | 0 | ($abi, $os, $cpu) = ('', '', ''); | ||||
162 | } | ||||||
163 | |||||||
164 | ## Global defaults | ||||||
165 | |||||||
166 | 4 | 4 | my @compile_flags = qw( | ||||
167 | CFLAGS | ||||||
168 | CXXFLAGS | ||||||
169 | OBJCFLAGS | ||||||
170 | OBJCXXFLAGS | ||||||
171 | FFLAGS | ||||||
172 | FCFLAGS | ||||||
173 | GCJFLAGS | ||||||
174 | ); | ||||||
175 | |||||||
176 | 4 | 4 | my $default_flags; | ||||
177 | my $default_d_flags; | ||||||
178 | 4 | 8 | if ($opts_build->has('noopt')) { | ||||
179 | 0 | 0 | $default_flags = '-g -O0'; | ||||
180 | 0 | 0 | $default_d_flags = '-fdebug'; | ||||
181 | } else { | ||||||
182 | 4 | 4 | $default_flags = '-g -O2'; | ||||
183 | 4 | 1 | $default_d_flags = '-frelease'; | ||||
184 | } | ||||||
185 | 4 | 10 | $flags->append($_, $default_flags) foreach @compile_flags; | ||||
186 | 4 | 4 | $flags->append('DFLAGS', $default_d_flags); | ||||
187 | |||||||
188 | ## Area: future | ||||||
189 | |||||||
190 | 4 | 4 | if ($use_feature{future}{lfs}) { | ||||
191 | 0 | 0 | my ($abi_bits, $abi_endian) = Dpkg::Arch::debarch_to_abiattrs($arch); | ||||
192 | 0 | 0 | my $cpu_bits = Dpkg::Arch::debarch_to_cpubits($arch); | ||||
193 | |||||||
194 | 0 | 0 | if ($abi_bits == 32 and $cpu_bits == 32) { | ||||
195 | 0 | 0 | $flags->append('CPPFLAGS', | ||||
196 | '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'); | ||||||
197 | } | ||||||
198 | } | ||||||
199 | |||||||
200 | ## Area: qa | ||||||
201 | |||||||
202 | # Warnings that detect actual bugs. | ||||||
203 | 4 | 4 | if ($use_feature{qa}{bug}) { | ||||
204 | # C flags | ||||||
205 | 0 | 0 | my @cflags = qw( | ||||
206 | implicit-function-declaration | ||||||
207 | ); | ||||||
208 | 0 | 0 | foreach my $warnflag (@cflags) { | ||||
209 | 0 | 0 | $flags->append('CFLAGS', "-Werror=$warnflag"); | ||||
210 | } | ||||||
211 | |||||||
212 | # C/C++ flags | ||||||
213 | 0 | 0 | my @cfamilyflags = qw( | ||||
214 | array-bounds | ||||||
215 | clobbered | ||||||
216 | volatile-register-var | ||||||
217 | ); | ||||||
218 | 0 | 0 | foreach my $warnflag (@cfamilyflags) { | ||||
219 | 0 | 0 | $flags->append('CFLAGS', "-Werror=$warnflag"); | ||||
220 | 0 | 0 | $flags->append('CXXFLAGS', "-Werror=$warnflag"); | ||||
221 | } | ||||||
222 | } | ||||||
223 | |||||||
224 | # Inject dummy canary options to detect issues with build flag propagation. | ||||||
225 | 4 | 3 | if ($use_feature{qa}{canary}) { | ||||
226 | 0 | 0 | require Digest::MD5; | ||||
227 | 0 | 0 | my $id = Digest::MD5::md5_hex(int rand 4096); | ||||
228 | |||||||
229 | 0 | 0 | foreach my $flag (qw(CPPFLAGS CFLAGS OBJCFLAGS CXXFLAGS OBJCXXFLAGS)) { | ||||
230 | 0 | 0 | $flags->append($flag, "-D__DEB_CANARY_${flag}_${id}__"); | ||||
231 | } | ||||||
232 | 0 | 0 | $flags->append('LDFLAGS', "-Wl,-z,deb-canary-${id}"); | ||||
233 | } | ||||||
234 | |||||||
235 | ## Area: reproducible | ||||||
236 | |||||||
237 | 4 | 5 | my $build_path; | ||||
238 | |||||||
239 | # Mask features that might have an unsafe usage. | ||||||
240 | 4 | 7 | if ($use_feature{reproducible}{fixfilepath} or | ||||
241 | $use_feature{reproducible}{fixdebugpath}) { | ||||||
242 | 4 | 7 | require Cwd; | ||||
243 | |||||||
244 | 4 | 20 | $build_path = $ENV{DEB_BUILD_PATH} || Cwd::getcwd(); | ||||
245 | |||||||
246 | # If we have any unsafe character in the path, disable the flag, | ||||||
247 | # so that we do not need to worry about escaping the characters | ||||||
248 | # on output. | ||||||
249 | 4 | 6 | if ($build_path =~ m/[^-+:.0-9a-zA-Z~\/_]/) { | ||||
250 | 0 | 0 | $use_feature{reproducible}{fixfilepath} = 0; | ||||
251 | 0 | 0 | $use_feature{reproducible}{fixdebugpath} = 0; | ||||
252 | } | ||||||
253 | } | ||||||
254 | |||||||
255 | # Warn when the __TIME__, __DATE__ and __TIMESTAMP__ macros are used. | ||||||
256 | 4 | 4 | if ($use_feature{reproducible}{timeless}) { | ||||
257 | 4 | 4 | $flags->append('CPPFLAGS', '-Wdate-time'); | ||||
258 | } | ||||||
259 | |||||||
260 | # Avoid storing the build path in the binaries. | ||||||
261 | 4 | 10 | if ($use_feature{reproducible}{fixfilepath} or | ||||
262 | $use_feature{reproducible}{fixdebugpath}) { | ||||||
263 | 4 | 1 | my $map; | ||||
264 | |||||||
265 | # -ffile-prefix-map is a superset of -fdebug-prefix-map, prefer it | ||||||
266 | # if both are set. | ||||||
267 | 4 | 4 | if ($use_feature{reproducible}{fixfilepath}) { | ||||
268 | 4 | 3 | $map = '-ffile-prefix-map=' . $build_path . '=.'; | ||||
269 | } else { | ||||||
270 | 0 | 0 | $map = '-fdebug-prefix-map=' . $build_path . '=.'; | ||||
271 | } | ||||||
272 | |||||||
273 | 4 | 4 | $flags->append($_, $map) foreach @compile_flags; | ||||
274 | } | ||||||
275 | |||||||
276 | ## Area: optimize | ||||||
277 | |||||||
278 | 4 | 6 | if ($use_feature{optimize}{lto}) { | ||||
279 | 0 | 0 | my $flag = '-flto=auto -ffat-lto-objects'; | ||||
280 | 0 | 0 | $flags->append($_, $flag) foreach (@compile_flags, 'LDFLAGS'); | ||||
281 | } | ||||||
282 | |||||||
283 | ## Area: sanitize | ||||||
284 | |||||||
285 | # Handle logical feature interactions. | ||||||
286 | 4 | 4 | if ($use_feature{sanitize}{address} and $use_feature{sanitize}{thread}) { | ||||
287 | # Disable the thread sanitizer when the address one is active, they | ||||||
288 | # are mutually incompatible. | ||||||
289 | 0 | 0 | $use_feature{sanitize}{thread} = 0; | ||||
290 | } | ||||||
291 | 4 | 11 | if ($use_feature{sanitize}{address} or $use_feature{sanitize}{thread}) { | ||||
292 | # Disable leak sanitizer, it is implied by the address or thread ones. | ||||||
293 | 0 | 0 | $use_feature{sanitize}{leak} = 0; | ||||
294 | } | ||||||
295 | |||||||
296 | 4 | 4 | if ($use_feature{sanitize}{address}) { | ||||
297 | 0 | 0 | my $flag = '-fsanitize=address -fno-omit-frame-pointer'; | ||||
298 | 0 | 0 | $flags->append('CFLAGS', $flag); | ||||
299 | 0 | 0 | $flags->append('CXXFLAGS', $flag); | ||||
300 | 0 | 0 | $flags->append('LDFLAGS', '-fsanitize=address'); | ||||
301 | } | ||||||
302 | |||||||
303 | 4 | 3 | if ($use_feature{sanitize}{thread}) { | ||||
304 | 0 | 0 | my $flag = '-fsanitize=thread'; | ||||
305 | 0 | 0 | $flags->append('CFLAGS', $flag); | ||||
306 | 0 | 0 | $flags->append('CXXFLAGS', $flag); | ||||
307 | 0 | 0 | $flags->append('LDFLAGS', $flag); | ||||
308 | } | ||||||
309 | |||||||
310 | 4 | 3 | if ($use_feature{sanitize}{leak}) { | ||||
311 | 0 | 0 | $flags->append('LDFLAGS', '-fsanitize=leak'); | ||||
312 | } | ||||||
313 | |||||||
314 | 4 | 4 | if ($use_feature{sanitize}{undefined}) { | ||||
315 | 0 | 0 | my $flag = '-fsanitize=undefined'; | ||||
316 | 0 | 0 | $flags->append('CFLAGS', $flag); | ||||
317 | 0 | 0 | $flags->append('CXXFLAGS', $flag); | ||||
318 | 0 | 0 | $flags->append('LDFLAGS', $flag); | ||||
319 | } | ||||||
320 | |||||||
321 | ## Area: hardening | ||||||
322 | |||||||
323 | # Mask builtin features that are not enabled by default in the compiler. | ||||||
324 | 4 72 | 4 46 | my %builtin_pie_arch = map { $_ => 1 } qw( | ||||
325 | amd64 | ||||||
326 | arm64 | ||||||
327 | armel | ||||||
328 | armhf | ||||||
329 | hurd-i386 | ||||||
330 | i386 | ||||||
331 | kfreebsd-amd64 | ||||||
332 | kfreebsd-i386 | ||||||
333 | mips | ||||||
334 | mipsel | ||||||
335 | mips64el | ||||||
336 | powerpc | ||||||
337 | ppc64 | ||||||
338 | ppc64el | ||||||
339 | riscv64 | ||||||
340 | s390x | ||||||
341 | sparc | ||||||
342 | sparc64 | ||||||
343 | ); | ||||||
344 | 4 | 8 | if (not exists $builtin_pie_arch{$arch}) { | ||||
345 | 0 | 0 | $builtin_feature{hardening}{pie} = 0; | ||||
346 | } | ||||||
347 | |||||||
348 | # Mask features that are not available on certain architectures. | ||||||
349 | 4 | 22 | if ($os !~ /^(?:linux|kfreebsd|knetbsd|hurd)$/ or | ||||
350 | $cpu =~ /^(?:hppa|avr32)$/) { | ||||||
351 | # Disabled on non-(linux/kfreebsd/knetbsd/hurd). | ||||||
352 | # Disabled on hppa, avr32 | ||||||
353 | # (#574716). | ||||||
354 | 0 | 0 | $use_feature{hardening}{pie} = 0; | ||||
355 | } | ||||||
356 | 4 | 13 | if ($cpu =~ /^(?:ia64|alpha|hppa|nios2)$/ or $arch eq 'arm') { | ||||
357 | # Stack protector disabled on ia64, alpha, hppa, nios2. | ||||||
358 | # "warning: -fstack-protector not supported for this target" | ||||||
359 | # Stack protector disabled on arm (ok on armel). | ||||||
360 | # compiler supports it incorrectly (leads to SEGV) | ||||||
361 | 0 | 0 | $use_feature{hardening}{stackprotector} = 0; | ||||
362 | } | ||||||
363 | 4 | 5 | if ($cpu =~ /^(?:ia64|hppa|avr32)$/) { | ||||
364 | # relro not implemented on ia64, hppa, avr32. | ||||||
365 | 0 | 0 | $use_feature{hardening}{relro} = 0; | ||||
366 | } | ||||||
367 | |||||||
368 | # Mask features that might be influenced by other flags. | ||||||
369 | 4 | 4 | if ($opts_build->has('noopt')) { | ||||
370 | # glibc 2.16 and later warn when using -O0 and _FORTIFY_SOURCE. | ||||||
371 | 0 | 0 | $use_feature{hardening}{fortify} = 0; | ||||
372 | } | ||||||
373 | |||||||
374 | # Handle logical feature interactions. | ||||||
375 | 4 | 4 | if ($use_feature{hardening}{relro} == 0) { | ||||
376 | # Disable bindnow if relro is not enabled, since it has no | ||||||
377 | # hardening ability without relro and may incur load penalties. | ||||||
378 | 0 | 0 | $use_feature{hardening}{bindnow} = 0; | ||||
379 | } | ||||||
380 | 4 | 3 | if ($use_feature{hardening}{stackprotector} == 0) { | ||||
381 | # Disable stackprotectorstrong if stackprotector is disabled. | ||||||
382 | 0 | 0 | $use_feature{hardening}{stackprotectorstrong} = 0; | ||||
383 | } | ||||||
384 | |||||||
385 | # PIE | ||||||
386 | 4 | 10 | if (defined $use_feature{hardening}{pie} and | ||||
387 | $use_feature{hardening}{pie} and | ||||||
388 | not $builtin_feature{hardening}{pie}) { | ||||||
389 | 0 | 0 | my $flag = "-specs=$Dpkg::DATADIR/pie-compile.specs"; | ||||
390 | 0 | 0 | $flags->append($_, $flag) foreach @compile_flags; | ||||
391 | 0 | 0 | $flags->append('LDFLAGS', "-specs=$Dpkg::DATADIR/pie-link.specs"); | ||||
392 | } elsif (defined $use_feature{hardening}{pie} and | ||||||
393 | not $use_feature{hardening}{pie} and | ||||||
394 | $builtin_feature{hardening}{pie}) { | ||||||
395 | 0 | 0 | my $flag = "-specs=$Dpkg::DATADIR/no-pie-compile.specs"; | ||||
396 | 0 | 0 | $flags->append($_, $flag) foreach @compile_flags; | ||||
397 | 0 | 0 | $flags->append('LDFLAGS', "-specs=$Dpkg::DATADIR/no-pie-link.specs"); | ||||
398 | } | ||||||
399 | |||||||
400 | # Stack protector | ||||||
401 | 4 | 9 | if ($use_feature{hardening}{stackprotectorstrong}) { | ||||
402 | 4 | 3 | my $flag = '-fstack-protector-strong'; | ||||
403 | 4 | 4 | $flags->append($_, $flag) foreach @compile_flags; | ||||
404 | } elsif ($use_feature{hardening}{stackprotector}) { | ||||||
405 | 0 | 0 | my $flag = '-fstack-protector --param=ssp-buffer-size=4'; | ||||
406 | 0 | 0 | $flags->append($_, $flag) foreach @compile_flags; | ||||
407 | } | ||||||
408 | |||||||
409 | # Fortify Source | ||||||
410 | 4 | 3 | if ($use_feature{hardening}{fortify}) { | ||||
411 | 4 | 4 | $flags->append('CPPFLAGS', '-D_FORTIFY_SOURCE=2'); | ||||
412 | } | ||||||
413 | |||||||
414 | # Format Security | ||||||
415 | 4 | 4 | if ($use_feature{hardening}{format}) { | ||||
416 | 4 | 2 | my $flag = '-Wformat -Werror=format-security'; | ||||
417 | 4 | 4 | $flags->append('CFLAGS', $flag); | ||||
418 | 4 | 6 | $flags->append('CXXFLAGS', $flag); | ||||
419 | 4 | 4 | $flags->append('OBJCFLAGS', $flag); | ||||
420 | 4 | 2 | $flags->append('OBJCXXFLAGS', $flag); | ||||
421 | } | ||||||
422 | |||||||
423 | # Read-only Relocations | ||||||
424 | 4 | 5 | if ($use_feature{hardening}{relro}) { | ||||
425 | 4 | 4 | $flags->append('LDFLAGS', '-Wl,-z,relro'); | ||||
426 | } | ||||||
427 | |||||||
428 | # Bindnow | ||||||
429 | 4 | 5 | if ($use_feature{hardening}{bindnow}) { | ||||
430 | 0 | 0 | $flags->append('LDFLAGS', '-Wl,-z,now'); | ||||
431 | } | ||||||
432 | |||||||
433 | ## Commit | ||||||
434 | |||||||
435 | # Set used features to their builtin setting if unset. | ||||||
436 | 4 | 5 | foreach my $area (sort keys %builtin_feature) { | ||||
437 | 4 4 | 2 4 | foreach my $feature (keys %{$builtin_feature{$area}}) { | ||||
438 | 4 | 11 | $use_feature{$area}{$feature} //= $builtin_feature{$area}{$feature}; | ||||
439 | } | ||||||
440 | } | ||||||
441 | |||||||
442 | # Store the feature usage. | ||||||
443 | 4 | 8 | foreach my $area (sort keys %use_feature) { | ||||
444 | 24 96 | 37 100 | while (my ($feature, $enabled) = each %{$use_feature{$area}}) { | ||||
445 | 72 | 44 | $flags->set_feature($area, $feature, $enabled); | ||||
446 | } | ||||||
447 | } | ||||||
448 | } | ||||||
449 | |||||||
450 | sub _build_tainted_by { | ||||||
451 | 0 | my $self = shift; | |||||
452 | 0 | my %tainted; | |||||
453 | |||||||
454 | 0 | foreach my $pathname (qw(/bin /sbin /lib /lib32 /libo32 /libx32 /lib64)) { | |||||
455 | 0 | next unless -l $pathname; | |||||
456 | |||||||
457 | 0 | my $linkname = readlink $pathname; | |||||
458 | 0 | if ($linkname eq "usr$pathname" or $linkname eq "/usr$pathname") { | |||||
459 | 0 | $tainted{'merged-usr-via-aliased-dirs'} = 1; | |||||
460 | 0 | last; | |||||
461 | } | ||||||
462 | } | ||||||
463 | |||||||
464 | 0 | require File::Find; | |||||
465 | 0 | my %usr_local_types = ( | |||||
466 | configs => [ qw(etc) ], | ||||||
467 | includes => [ qw(include) ], | ||||||
468 | programs => [ qw(bin sbin) ], | ||||||
469 | libraries => [ qw(lib) ], | ||||||
470 | ); | ||||||
471 | 0 | foreach my $type (keys %usr_local_types) { | |||||
472 | File::Find::find({ | ||||||
473 | 0 | wanted => sub { $tainted{"usr-local-has-$type"} = 1 if -f }, | |||||
474 | no_chdir => 1, | ||||||
475 | 0 0 0 0 | }, grep { -d } map { "/usr/local/$_" } @{$usr_local_types{$type}}); | |||||
476 | } | ||||||
477 | |||||||
478 | 0 | my @tainted = sort keys %tainted; | |||||
479 | 0 | return @tainted; | |||||
480 | } | ||||||
481 | |||||||
482 - 488 | =head1 CHANGES =head2 Version 0.xx This is a private module. =cut | ||||||
489 | |||||||
490 | 1; |