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 |