[ Bcc: debian-dpkg to get a wider audience ] Hello,
during Debconf I discussed with doko and a few of the tech-ctte members to find a good solution for the problem of enabling hardening build flags. Following that discussion I worked on a few dpkg-buildflags enhancement that are now in the master branch. In this discussion it has been agreed that it's ok to enable hardening build flags by default given that dpkg-buildflags now has everything required to disable a specific hardening feature. The attached patches (corresponding to my pu/build-flags branch) add the hardening build flags by default. Each hardening feature can be enabled/disabled via the DEB_BUILD_MAINT_OPTIONS environment variable: DEB_BUILD_MAINT_OPTIONS="hardening=+pie,-relro" The special value "all" enables/disables all hardening features. Thus to disable hardening entirely you can do: DEB_BUILD_MAINT_OPTIONS="hardening=-all" PIE is disabled by default, any maintainer wishing to use it has to enable it explicitly. Before I can merge this, we still need some documentation. Kees Cook proposed to write it so I'm waiting on him for this. I also wonder whether we should keep -Werror=format-security given that no archive rebuild has been made with this option so we don't really know how many packages will be affected by this. Cheers, -- Raphaël Hertzog ◈ Debian Developer Follow my Debian News ▶ http://RaphaelHertzog.com (English) ▶ http://RaphaelHertzog.fr (Français)
commit ac22f50cfa66e43101d767d6f5cb9c7a79fe0872 Author: Raphaël Hertzog <hert...@debian.org> Date: Tue Aug 2 14:15:17 2011 +0200 Dpkg::BuildOptions: enable usage of alternative variable names diff --git a/scripts/Dpkg/BuildOptions.pm b/scripts/Dpkg/BuildOptions.pm index 2638017..1accdec 100644 --- a/scripts/Dpkg/BuildOptions.pm +++ b/scripts/Dpkg/BuildOptions.pm @@ -19,7 +19,7 @@ package Dpkg::BuildOptions; use strict; use warnings; -our $VERSION = "1.00"; +our $VERSION = "1.01"; use Dpkg::Gettext; use Dpkg::ErrorHandling; @@ -33,16 +33,18 @@ Dpkg::BuildOptions - parse and update build options =head1 DESCRIPTION The Dpkg::BuildOptions object can be used to manipulate options stored -in the DEB_BUILD_OPTIONS environment variable. +in environment variables like DEB_BUILD_OPTIONS and +DEB_BUILD_MAINT_OPTIONS. =head1 FUNCTIONS =over 4 -=item my $bo = Dpkg::BuildOptions->new() +=item my $bo = Dpkg::BuildOptions->new(%opts) Create a new Dpkg::BuildOptions object. It will be initialized based -on the value of the DEB_BUILD_OPTIONS environment variable. +on the value of the environment variable named $opts{'envvar'} (or +DEB_BUILD_OPTIONS if that option is not set). =cut @@ -53,9 +55,10 @@ sub new { my $self = { options => {}, source => {}, + envvar => $opts{'envvar'} // "DEB_BUILD_OPTIONS", }; bless $self, $class; - $self->merge($ENV{DEB_BUILD_OPTIONS}, "DEB_BUILD_OPTIONS"); + $self->merge($ENV{$self->{'envvar'}}, $self->{'envvar'}); return $self; } @@ -169,14 +172,14 @@ sub output { =item $bo->export([$var]) Export the build options to the given environment variable. If omitted, -DEB_BUILD_OPTIONS is assumed. The value set to the variable is also -returned. +the environment variable defined at creation time is assumed. The value +set to the variable is also returned. =cut sub export { my ($self, $var) = @_; - $var = "DEB_BUILD_OPTIONS" unless defined $var; + $var = $self->{'envvar'} unless defined $var; my $content = $self->output(); $ENV{$var} = $content; return $content; @@ -184,6 +187,13 @@ sub export { =back +=head1 CHANGES + +=head2 Version 1.01 + +Enable to use another environment variable instead of DEB_BUILD_OPTIONS. +Thus add support for the "envvar" option at creation time. + =head1 AUTHOR Raphaël Hertzog <hert...@debian.org> diff --git a/scripts/t/300_Dpkg_BuildOptions.t b/scripts/t/300_Dpkg_BuildOptions.t index d5979e4..a715549 100644 --- a/scripts/t/300_Dpkg_BuildOptions.t +++ b/scripts/t/300_Dpkg_BuildOptions.t @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -use Test::More tests => 22; +use Test::More tests => 24; use Dpkg::ErrorHandling; use strict; @@ -66,3 +66,7 @@ $ENV{DEB_BUILD_OPTIONS} = 'foobar'; $dbo = Dpkg::BuildOptions->new(); $dbo->set("noopt", 1); is($dbo->output(), "foobar noopt", "output"); + +$dbo = Dpkg::BuildOptions->new(envvar => "OTHER_VARIABLE"); +is($dbo->get("parallel"), 5, "import from other variable, check parallel"); +ok($dbo->has("noopt"), "import from other variable, check noopt");
commit 086144899ff3fa2d6703e2da9fe44e607d23fd18 Author: Raphaël Hertzog <hert...@debian.org> Date: Wed Jul 27 22:10:49 2011 +0200 WIP: dpkg-buildflags: emit hardening build flags by default All the hardening build flags supported by hardening-includes are supported except that PIE is not enabled by default (just like the corresponding gcc patch doesn't enable it by default). FIXME: decide if we keep -Werror=format-security FIXME: add documentation Inspired by the work of Kees Cook <k...@debian.org>. diff --git a/scripts/Dpkg/BuildFlags.pm b/scripts/Dpkg/BuildFlags.pm index 9bc473a..5479af0 100644 --- a/scripts/Dpkg/BuildFlags.pm +++ b/scripts/Dpkg/BuildFlags.pm @@ -1,5 +1,9 @@ # Copyright © 2010-2011 Raphaël Hertzog <hert...@debian.org> # +# Hardening build flags handling derived from work of: +# Copyright © 2009-2011 Kees Cook <k...@debian.org> +# Copyright © 2007-2008 Canonical, Ltd. +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -24,6 +28,7 @@ use Dpkg::Gettext; use Dpkg::BuildOptions; use Dpkg::ErrorHandling; use Dpkg::Vendor qw(run_vendor_hook); +use Dpkg::Arch qw(get_host_arch debarch_to_debtriplet); =encoding utf8 @@ -84,9 +89,93 @@ sub load_vendor_defaults { FFLAGS => 'vendor', LDFLAGS => 'vendor', }; + $self->add_hardening_flags(); run_vendor_hook("update-buildflags", $self); } +=item $bf->add_hardening_flags() + +Add hardening build flags to the current set of flags. It's always called +by load_vendor_defaults(). + +=cut + +sub add_hardening_flags { + my ($self) = @_; + my $arch = get_host_arch(); + my ($abi, $os, $cpu) = debarch_to_debtriplet($arch); + + # Decide what's enabled + my %use_feature = ( + "pie" => 0, + "stackprotector" => 1, + "fortify" => 1, + "format" => 1, + "relro" => 1, + "bindnow" => 1 + ); + my $opts = Dpkg::BuildOptions->new(envvar => "DEB_BUILD_MAINT_OPTIONS"); + foreach my $feature (split(",", $opts->get("hardening") // "")) { + $feature = lc($feature); + if ($feature =~ s/^([+-])//) { + my $value = ($1 eq "+") ? 1 : 0; + if ($feature eq "all") { + $use_feature{$_} = $value foreach keys %use_feature; + } else { + if (exists $use_feature{$feature}) { + $use_feature{$feature} = $value; + } else { + warning(_g("unknown hardening feature: %s"), $feature); + } + } + } else { + warning(_g("incorrect value in hardening option of " . + "DEB_BUILD_MAINT_OPTIONS: %s"), $feature); + } + } + + # PIE + if ($use_feature{"pie"} and + $os =~ /^(linux|knetbsd|hurd)$/ and + $cpu !~ /^(hppa|m68k|mips|mipsel|avr32)$/) { + # Only on linux/knetbsd/hurd (see #430455 and #586215) + # Disabled on hppa, m68k (#451192), mips/mipsel (#532821), avr32 + # (#574716) + $self->append("CFLAGS", "-fPIE"); + $self->append("CXXFLAGS", "-fPIE"); + $self->append("LDFLAGS", "-fPIE -pie"); + } + # Stack protector + if ($use_feature{"stackprotector"} and + $cpu !~ /^(ia64|alpha|mips|mipsel|hppa)$/ and $arch ne "arm") { + # Stack protector disabled on ia64, alpha, mips, mipsel, hppa. + # "warning: -fstack-protector not supported for this target" + # Stack protector disabled on arm (ok on armel). + # compiler supports it incorrectly (leads to SEGV) + $self->append("CFLAGS", "-fstack-protector --param=ssp-buffer-size=4"); + $self->append("CXXFLAGS", "-fstack-protector --param=ssp-buffer-size=4"); + } + # Fortify + my $build_opts = Dpkg::BuildOptions->new(); + if ($use_feature{"fortify"} and not $build_opts->has("noopt")) { + $self->append("CFLAGS", "-D_FORTIFY_SOURCE=2"); + $self->append("CXXFLAGS", "-D_FORTIFY_SOURCE=2"); + } + # Format + if ($use_feature{"format"}) { + $self->append("CFLAGS", "-Wformat -Wformat-security -Werror=format-security"); + $self->append("CXXFLAGS", "-Wformat -Wformat-security -Werror=format-security"); + } + # Relro + if ($use_feature{"relro"} and $cpu !~ /^(ia64|hppa|avr32)$/) { + $self->append("LDFLAGS", "-Wl,-z,relro"); + } + # Bindnow + if ($use_feature{"bindnow"}) { + $self->append("LDFLAGS", "-Wl,-z,now"); + } +} + =item $bf->load_system_config() Update flags from the system configuration.