This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=cbdd27b11384a397e60426fce1eb41947dc0b248 commit cbdd27b11384a397e60426fce1eb41947dc0b248 Author: Guillem Jover <[email protected]> AuthorDate: Wed Jun 24 04:12:11 2020 +0200 Dpkg::Vendor::Debian: Generalize feature areas defaults Split setting the build features to use, from acting on them to set the build flags based on these. This makes it possible to override these feature defaults by vendors inheriting from a parent, so that they do not have to mangle the generated build flags, or need to modify the parent vendor module to be able to change those defaults. --- scripts/Dpkg/Vendor/Debian.pm | 313 ++++++++++++++++++++++------------------- scripts/Dpkg/Vendor/Default.pm | 13 ++ 2 files changed, 179 insertions(+), 147 deletions(-) diff --git a/scripts/Dpkg/Vendor/Debian.pm b/scripts/Dpkg/Vendor/Debian.pm index c1d6471da..e36f21664 100644 --- a/scripts/Dpkg/Vendor/Debian.pm +++ b/scripts/Dpkg/Vendor/Debian.pm @@ -76,6 +76,7 @@ sub run_hook { $$textref .= "Bug-Ubuntu: https://bugs.launchpad.net/bugs/$bug\n"; } } elsif ($hook eq 'update-buildflags') { + $self->set_build_features(@params); $self->_add_build_flags(@params); } elsif ($hook eq 'builtin-system-build-paths') { return qw(/build/); @@ -93,7 +94,7 @@ sub run_hook { } } -sub _add_build_flags { +sub set_build_features { my ($self, $flags) = @_; # Default feature states. @@ -161,83 +162,17 @@ sub _add_build_flags { ($abi, $os, $cpu) = ('', '', ''); } - ## Global defaults - - my @compile_flags = qw( - CFLAGS - CXXFLAGS - OBJCFLAGS - OBJCXXFLAGS - FFLAGS - FCFLAGS - GCJFLAGS - ); - - my $default_flags; - my $default_d_flags; - my $optimize_level; - if ($opts_build->has('noopt')) { - $optimize_level = 0; - } else { - $optimize_level = 2; - } - $flags->set_option_value('optimize-level', $optimize_level); - $default_flags = "-g -O$optimize_level"; - if ($optimize_level == 0) { - $default_d_flags = '-fdebug'; - } else { - $default_d_flags = '-frelease'; - } - $flags->append($_, $default_flags) foreach @compile_flags; - $flags->append('DFLAGS', $default_d_flags); - ## Area: future if ($use_feature{future}{lfs}) { my ($abi_bits, $abi_endian) = Dpkg::Arch::debarch_to_abiattrs($arch); my $cpu_bits = Dpkg::Arch::debarch_to_cpubits($arch); - if ($abi_bits == 32 and $cpu_bits == 32) { - $flags->append('CPPFLAGS', - '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'); - } - } - - ## Area: qa - - # Warnings that detect actual bugs. - if ($use_feature{qa}{bug}) { - # C flags - my @cflags = qw( - implicit-function-declaration - ); - foreach my $warnflag (@cflags) { - $flags->append('CFLAGS', "-Werror=$warnflag"); - } - - # C/C++ flags - my @cfamilyflags = qw( - array-bounds - clobbered - volatile-register-var - ); - foreach my $warnflag (@cfamilyflags) { - $flags->append('CFLAGS', "-Werror=$warnflag"); - $flags->append('CXXFLAGS', "-Werror=$warnflag"); + if ($abi_bits != 32 or $cpu_bits != 32) { + $use_feature{future}{lfs} = 0; } } - # Inject dummy canary options to detect issues with build flag propagation. - if ($use_feature{qa}{canary}) { - require Digest::MD5; - my $id = Digest::MD5::md5_hex(int rand 4096); - - foreach my $flag (qw(CPPFLAGS CFLAGS OBJCFLAGS CXXFLAGS OBJCXXFLAGS)) { - $flags->append($flag, "-D__DEB_CANARY_${flag}_${id}__"); - } - $flags->append('LDFLAGS', "-Wl,-z,deb-canary-${id}"); - } - ## Area: reproducible # Mask features that might have an unsafe usage. @@ -258,33 +193,12 @@ sub _add_build_flags { } } - # Warn when the __TIME__, __DATE__ and __TIMESTAMP__ macros are used. - if ($use_feature{reproducible}{timeless}) { - $flags->append('CPPFLAGS', '-Wdate-time'); - } - - # Avoid storing the build path in the binaries. - if ($use_feature{reproducible}{fixfilepath} or - $use_feature{reproducible}{fixdebugpath}) { - my $build_path = $flags->get_option_value('build-path'); - my $map; - - # -ffile-prefix-map is a superset of -fdebug-prefix-map, prefer it - # if both are set. - if ($use_feature{reproducible}{fixfilepath}) { - $map = '-ffile-prefix-map=' . $build_path . '=.'; - } else { - $map = '-fdebug-prefix-map=' . $build_path . '=.'; - } - - $flags->append($_, $map) foreach @compile_flags; - } - ## Area: optimize - if ($use_feature{optimize}{lto}) { - my $flag = '-flto=auto -ffat-lto-objects'; - $flags->append($_, $flag) foreach (@compile_flags, 'LDFLAGS'); + if ($opts_build->has('noopt')) { + $flags->set_option_value('optimize-level', 0); + } else { + $flags->set_option_value('optimize-level', 2); } ## Area: sanitize @@ -300,31 +214,6 @@ sub _add_build_flags { $use_feature{sanitize}{leak} = 0; } - if ($use_feature{sanitize}{address}) { - my $flag = '-fsanitize=address -fno-omit-frame-pointer'; - $flags->append('CFLAGS', $flag); - $flags->append('CXXFLAGS', $flag); - $flags->append('LDFLAGS', '-fsanitize=address'); - } - - if ($use_feature{sanitize}{thread}) { - my $flag = '-fsanitize=thread'; - $flags->append('CFLAGS', $flag); - $flags->append('CXXFLAGS', $flag); - $flags->append('LDFLAGS', $flag); - } - - if ($use_feature{sanitize}{leak}) { - $flags->append('LDFLAGS', '-fsanitize=leak'); - } - - if ($use_feature{sanitize}{undefined}) { - my $flag = '-fsanitize=undefined'; - $flags->append('CFLAGS', $flag); - $flags->append('CXXFLAGS', $flag); - $flags->append('LDFLAGS', $flag); - } - ## Area: hardening # Mask builtin features that are not enabled by default in the compiler. @@ -389,37 +278,183 @@ sub _add_build_flags { $use_feature{hardening}{stackprotectorstrong} = 0; } + ## Commit + + # Set used features to their builtin setting if unset. + foreach my $area (sort keys %builtin_feature) { + while (my ($feature, $enabled) = each %{$builtin_feature{$area}}) { + $flags->set_builtin($area, $feature, $enabled); + } + } + + # Store the feature usage. + foreach my $area (sort keys %use_feature) { + while (my ($feature, $enabled) = each %{$use_feature{$area}}) { + $flags->set_feature($area, $feature, $enabled); + } + } +} + +sub _add_build_flags { + my ($self, $flags) = @_; + + ## Global default flags + + my @compile_flags = qw( + CFLAGS + CXXFLAGS + OBJCFLAGS + OBJCXXFLAGS + FFLAGS + FCFLAGS + GCJFLAGS + ); + + my $default_flags; + my $default_d_flags; + + my $optimize_level = $flags->get_option_value('optimize-level'); + $default_flags = "-g -O$optimize_level"; + if ($optimize_level == 0) { + $default_d_flags = '-fdebug'; + } else { + $default_d_flags = '-frelease'; + } + + $flags->append($_, $default_flags) foreach @compile_flags; + $flags->append('DFLAGS', $default_d_flags); + + ## Area: future + + if ($flags->use_feature('future', 'lfs')) { + $flags->append('CPPFLAGS', + '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'); + } + + ## Area: qa + + # Warnings that detect actual bugs. + if ($flags->use_feature('qa', 'bug')) { + # C flags + my @cflags = qw( + implicit-function-declaration + ); + foreach my $warnflag (@cflags) { + $flags->append('CFLAGS', "-Werror=$warnflag"); + } + + # C/C++ flags + my @cfamilyflags = qw( + array-bounds + clobbered + volatile-register-var + ); + foreach my $warnflag (@cfamilyflags) { + $flags->append('CFLAGS', "-Werror=$warnflag"); + $flags->append('CXXFLAGS', "-Werror=$warnflag"); + } + } + + # Inject dummy canary options to detect issues with build flag propagation. + if ($flags->use_feature('qa', 'canary')) { + require Digest::MD5; + my $id = Digest::MD5::md5_hex(int rand 4096); + + foreach my $flag (qw(CPPFLAGS CFLAGS OBJCFLAGS CXXFLAGS OBJCXXFLAGS)) { + $flags->append($flag, "-D__DEB_CANARY_${flag}_${id}__"); + } + $flags->append('LDFLAGS', "-Wl,-z,deb-canary-${id}"); + } + + ## Area: reproducible + + # Warn when the __TIME__, __DATE__ and __TIMESTAMP__ macros are used. + if ($flags->use_feature('reproducible', 'timeless')) { + $flags->append('CPPFLAGS', '-Wdate-time'); + } + + # Avoid storing the build path in the binaries. + if ($flags->use_feature('reproducible', 'fixfilepath') or + $flags->use_feature('reproducible', 'fixdebugpath')) { + my $build_path = $flags->get_option_value('build-path'); + my $map; + + # -ffile-prefix-map is a superset of -fdebug-prefix-map, prefer it + # if both are set. + if ($flags->use_feature('reproducible', 'fixfilepath')) { + $map = '-ffile-prefix-map=' . $build_path . '=.'; + } else { + $map = '-fdebug-prefix-map=' . $build_path . '=.'; + } + + $flags->append($_, $map) foreach @compile_flags; + } + + ## Area: optimize + + if ($flags->use_feature('optimize', 'lto')) { + my $flag = '-flto=auto -ffat-lto-objects'; + $flags->append($_, $flag) foreach (@compile_flags, 'LDFLAGS'); + } + + ## Area: sanitize + + if ($flags->use_feature('sanitize', 'address')) { + my $flag = '-fsanitize=address -fno-omit-frame-pointer'; + $flags->append('CFLAGS', $flag); + $flags->append('CXXFLAGS', $flag); + $flags->append('LDFLAGS', '-fsanitize=address'); + } + + if ($flags->use_feature('sanitize', 'thread')) { + my $flag = '-fsanitize=thread'; + $flags->append('CFLAGS', $flag); + $flags->append('CXXFLAGS', $flag); + $flags->append('LDFLAGS', $flag); + } + + if ($flags->use_feature('sanitize', 'leak')) { + $flags->append('LDFLAGS', '-fsanitize=leak'); + } + + if ($flags->use_feature('sanitize', 'undefined')) { + my $flag = '-fsanitize=undefined'; + $flags->append('CFLAGS', $flag); + $flags->append('CXXFLAGS', $flag); + $flags->append('LDFLAGS', $flag); + } + + ## Area: hardening + # PIE - if (defined $use_feature{hardening}{pie} and - $use_feature{hardening}{pie} and - not $builtin_feature{hardening}{pie}) { + my $use_pie = $flags->use_feature('hardening', 'pie'); + my %hardening_builtins = $flags->get_builtins('hardening'); + if (defined $use_pie && $use_pie && ! $hardening_builtins{pie}) { my $flag = "-specs=$Dpkg::DATADIR/pie-compile.specs"; $flags->append($_, $flag) foreach @compile_flags; $flags->append('LDFLAGS', "-specs=$Dpkg::DATADIR/pie-link.specs"); - } elsif (defined $use_feature{hardening}{pie} and - not $use_feature{hardening}{pie} and - $builtin_feature{hardening}{pie}) { + } elsif (defined $use_pie && ! $use_pie && $hardening_builtins{pie}) { my $flag = "-specs=$Dpkg::DATADIR/no-pie-compile.specs"; $flags->append($_, $flag) foreach @compile_flags; $flags->append('LDFLAGS', "-specs=$Dpkg::DATADIR/no-pie-link.specs"); } # Stack protector - if ($use_feature{hardening}{stackprotectorstrong}) { + if ($flags->use_feature('hardening', 'stackprotectorstrong')) { my $flag = '-fstack-protector-strong'; $flags->append($_, $flag) foreach @compile_flags; - } elsif ($use_feature{hardening}{stackprotector}) { + } elsif ($flags->use_feature('hardening', 'stackprotector')) { my $flag = '-fstack-protector --param=ssp-buffer-size=4'; $flags->append($_, $flag) foreach @compile_flags; } # Fortify Source - if ($use_feature{hardening}{fortify}) { + if ($flags->use_feature('hardening', 'fortify')) { $flags->append('CPPFLAGS', '-D_FORTIFY_SOURCE=2'); } # Format Security - if ($use_feature{hardening}{format}) { + if ($flags->use_feature('hardening', 'format')) { my $flag = '-Wformat -Werror=format-security'; $flags->append('CFLAGS', $flag); $flags->append('CXXFLAGS', $flag); @@ -428,30 +463,14 @@ sub _add_build_flags { } # Read-only Relocations - if ($use_feature{hardening}{relro}) { + if ($flags->use_feature('hardening', 'relro')) { $flags->append('LDFLAGS', '-Wl,-z,relro'); } # Bindnow - if ($use_feature{hardening}{bindnow}) { + if ($flags->use_feature('hardening', 'bindnow')) { $flags->append('LDFLAGS', '-Wl,-z,now'); } - - ## Commit - - # Set used features to their builtin setting if unset. - foreach my $area (sort keys %builtin_feature) { - while (my ($feature, $state) = each %{$builtin_feature{$area}}) { - $flags->set_builtin($area, $feature, $state); - } - } - - # Store the feature usage. - foreach my $area (sort keys %use_feature) { - while (my ($feature, $enabled) = each %{$use_feature{$area}}) { - $flags->set_feature($area, $feature, $enabled); - } - } } sub _build_tainted_by { diff --git a/scripts/Dpkg/Vendor/Default.pm b/scripts/Dpkg/Vendor/Default.pm index 66d1bc6cb..8362b5b1a 100644 --- a/scripts/Dpkg/Vendor/Default.pm +++ b/scripts/Dpkg/Vendor/Default.pm @@ -203,6 +203,19 @@ sub run_hook { return; } +=item $vendor->set_build_features($flags) + +Sets the vendor build features, which will then be used to initialize the +build flags. + +=cut + +sub set_build_features { + my ($self, $flags) = @_; + + return; +} + =back =head1 CHANGES -- Dpkg.Org's dpkg

