OLD | NEW |
| (Empty) |
1 # Copyright © 2009-2011 Raphaël Hertzog <hertzog@debian.org> | |
2 # | |
3 # Hardening build flags handling derived from work of: | |
4 # Copyright © 2009-2011 Kees Cook <kees@debian.org> | |
5 # Copyright © 2007-2008 Canonical, Ltd. | |
6 # | |
7 # This program is free software; you can redistribute it and/or modify | |
8 # it under the terms of the GNU General Public License as published by | |
9 # the Free Software Foundation; either version 2 of the License, or | |
10 # (at your option) any later version. | |
11 # | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU General Public License for more details. | |
16 # | |
17 # You should have received a copy of the GNU General Public License | |
18 # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
19 | |
20 package Dpkg::Vendor::Debian; | |
21 | |
22 use strict; | |
23 use warnings; | |
24 | |
25 our $VERSION = '0.01'; | |
26 | |
27 use parent qw(Dpkg::Vendor::Default); | |
28 | |
29 use Dpkg::Gettext; | |
30 use Dpkg::ErrorHandling; | |
31 use Dpkg::Control::Types; | |
32 use Dpkg::BuildOptions; | |
33 use Dpkg::Arch qw(get_host_arch debarch_to_debtriplet); | |
34 | |
35 =encoding utf8 | |
36 | |
37 =head1 NAME | |
38 | |
39 Dpkg::Vendor::Debian - Debian vendor object | |
40 | |
41 =head1 DESCRIPTION | |
42 | |
43 This vendor object customize the behaviour of dpkg scripts | |
44 for Debian specific actions. | |
45 | |
46 =cut | |
47 | |
48 sub run_hook { | |
49 my ($self, $hook, @params) = @_; | |
50 | |
51 if ($hook eq 'keyrings') { | |
52 return ('/usr/share/keyrings/debian-keyring.gpg', | |
53 '/usr/share/keyrings/debian-maintainers.gpg'); | |
54 } elsif ($hook eq 'register-custom-fields') { | |
55 } elsif ($hook eq 'extend-patch-header') { | |
56 my ($textref, $ch_info) = @params; | |
57 if ($ch_info->{'Closes'}) { | |
58 foreach my $bug (split(/\s+/, $ch_info->{'Closes'})) { | |
59 $$textref .= "Bug-Debian: http://bugs.debian.org/$bug\n"; | |
60 } | |
61 } | |
62 | |
63 # XXX: Layer violation... | |
64 require Dpkg::Vendor::Ubuntu; | |
65 my $b = Dpkg::Vendor::Ubuntu::find_launchpad_closes($ch_info->{'Changes'
}); | |
66 foreach my $bug (@$b) { | |
67 $$textref .= "Bug-Ubuntu: https://bugs.launchpad.net/bugs/$bug\n"; | |
68 } | |
69 } elsif ($hook eq 'update-buildflags') { | |
70 $self->add_hardening_flags(@params); | |
71 } else { | |
72 return $self->SUPER::run_hook($hook, @params); | |
73 } | |
74 } | |
75 | |
76 sub add_hardening_flags { | |
77 my ($self, $flags) = @_; | |
78 my $arch = get_host_arch(); | |
79 my ($abi, $os, $cpu) = debarch_to_debtriplet($arch); | |
80 | |
81 unless (defined $abi and defined $os and defined $cpu) { | |
82 warning(_g("unknown host architecture '%s'"), $arch); | |
83 ($abi, $os, $cpu) = ('', '', ''); | |
84 } | |
85 | |
86 # Features enabled by default for all builds. | |
87 my %use_feature = ( | |
88 pie => 0, | |
89 stackprotector => 1, | |
90 fortify => 1, | |
91 format => 1, | |
92 relro => 1, | |
93 bindnow => 0, | |
94 ); | |
95 | |
96 # Adjust features based on Maintainer's desires. | |
97 my $opts = Dpkg::BuildOptions->new(envvar => 'DEB_BUILD_MAINT_OPTIONS'); | |
98 foreach my $feature (split(/,/, $opts->get('hardening') // '')) { | |
99 $feature = lc($feature); | |
100 if ($feature =~ s/^([+-])//) { | |
101 my $value = ($1 eq '+') ? 1 : 0; | |
102 if ($feature eq 'all') { | |
103 $use_feature{$_} = $value foreach keys %use_feature; | |
104 } else { | |
105 if (exists $use_feature{$feature}) { | |
106 $use_feature{$feature} = $value; | |
107 } else { | |
108 warning(_g('unknown hardening feature: %s'), $feature); | |
109 } | |
110 } | |
111 } else { | |
112 warning(_g('incorrect value in hardening option of ' . | |
113 'DEB_BUILD_MAINT_OPTIONS: %s'), $feature); | |
114 } | |
115 } | |
116 | |
117 # Mask features that are not available on certain architectures. | |
118 if ($os !~ /^(linux|knetbsd|hurd)$/ or | |
119 $cpu =~ /^(hppa|mips|mipsel|avr32)$/) { | |
120 # Disabled on non-linux/knetbsd/hurd (see #430455 and #586215). | |
121 # Disabled on hppa, mips/mipsel (#532821), avr32 | |
122 # (#574716). | |
123 $use_feature{pie} = 0; | |
124 } | |
125 if ($cpu =~ /^(ia64|alpha|mips|mipsel|hppa)$/ or $arch eq 'arm') { | |
126 # Stack protector disabled on ia64, alpha, mips, mipsel, hppa. | |
127 # "warning: -fstack-protector not supported for this target" | |
128 # Stack protector disabled on arm (ok on armel). | |
129 # compiler supports it incorrectly (leads to SEGV) | |
130 $use_feature{stackprotector} = 0; | |
131 } | |
132 if ($cpu =~ /^(ia64|hppa|avr32)$/) { | |
133 # relro not implemented on ia64, hppa, avr32. | |
134 $use_feature{relro} = 0; | |
135 } | |
136 | |
137 # Mask features that might be influenced by other flags. | |
138 if ($flags->{build_options}->has('noopt')) { | |
139 # glibc 2.16 and later warn when using -O0 and _FORTIFY_SOURCE. | |
140 $use_feature{fortify} = 0; | |
141 } | |
142 | |
143 # Handle logical feature interactions. | |
144 if ($use_feature{relro} == 0) { | |
145 # Disable bindnow if relro is not enabled, since it has no | |
146 # hardening ability without relro and may incur load penalties. | |
147 $use_feature{bindnow} = 0; | |
148 } | |
149 | |
150 # PIE | |
151 if ($use_feature{pie}) { | |
152 $flags->append('CFLAGS', '-fPIE'); | |
153 $flags->append('FFLAGS', '-fPIE'); | |
154 $flags->append('CXXFLAGS', '-fPIE'); | |
155 $flags->append('GCJFLAGS', '-fPIE'); | |
156 $flags->append('LDFLAGS', '-fPIE -pie'); | |
157 } | |
158 | |
159 # Stack protector | |
160 if ($use_feature{stackprotector}) { | |
161 $flags->append('CFLAGS', '-fstack-protector --param=ssp-buffer-size=4'); | |
162 $flags->append('FFLAGS', '-fstack-protector --param=ssp-buffer-size=4'); | |
163 $flags->append('CXXFLAGS', '-fstack-protector --param=ssp-buffer-size=4'
); | |
164 $flags->append('GCJFLAGS', '-fstack-protector --param=ssp-buffer-size=4'
); | |
165 } | |
166 | |
167 # Fortify Source | |
168 if ($use_feature{fortify}) { | |
169 $flags->append('CPPFLAGS', '-D_FORTIFY_SOURCE=2'); | |
170 } | |
171 | |
172 # Format Security | |
173 if ($use_feature{format}) { | |
174 $flags->append('CFLAGS', '-Wformat -Werror=format-security'); | |
175 $flags->append('CXXFLAGS', '-Wformat -Werror=format-security'); | |
176 } | |
177 | |
178 # Read-only Relocations | |
179 if ($use_feature{relro}) { | |
180 $flags->append('LDFLAGS', '-Wl,-z,relro'); | |
181 } | |
182 | |
183 # Bindnow | |
184 if ($use_feature{bindnow}) { | |
185 $flags->append('LDFLAGS', '-Wl,-z,now'); | |
186 } | |
187 | |
188 # Store the feature usage. | |
189 while (my ($feature, $enabled) = each %use_feature) { | |
190 $flags->set_feature('hardening', $feature, $enabled); | |
191 } | |
192 } | |
193 | |
194 1; | |
OLD | NEW |