use Getopt::Long ();
use Text::ParseWords ();
-our $VERSION = '0.07';
+our $VERSION = '0.08';
# CONSTANTS/VARIABLES
# fortify needs at least -O1, but -O2 is recommended anyway
);
my @def_cflags_stack = (
- '-fstack-protector',
+ '-fstack-protector', # keep first, used by cflags_stack_broken()
'--param[= ]ssp-buffer-size=4',
);
my @def_cflags_stack_strong = (
- '-fstack-protector-strong',
+ '-fstack-protector-strong', # keep first, used by cflags_stack_broken()
+);
+my @def_cflags_stack_bad = (
+ # Blacklist all stack protector options for simplicity.
+ '-fno-stack-protector',
+ '-fno-stack-protector-all',
+ '-fno-stack-protector-strong',
);
my @def_cflags_pie = (
'-fPIE',
\@def_cflags_fortify,
\@def_cflags_stack,
\@def_cflags_stack_strong,
+ \@def_cflags_stack_bad,
\@def_cflags_pie,
\@def_cxxflags,
\@def_cppflags,
@{$missing_flags_ref} = @missing_flags;
return 0;
}
+# Check if any of \@bad_flags occurs after $good_flag. Doesn't check if
+# $good_flag is present.
+sub flag_overwritten {
+ my ($line, $good_flag, $bad_flags) = @_;
+
+ if (not any_flags_used($line, @{$bad_flags})) {
+ return 0;
+ }
+
+ my $bad_pos = 0;
+ foreach my $flag (@{$bad_flags}) {
+ while ($line =~ /$flag/g) {
+ if ($bad_pos < $+[0]) {
+ $bad_pos = $+[0];
+ }
+ }
+ }
+ my $good_pos = 0;
+ while ($line =~ /$good_flag/g) {
+ $good_pos = $+[0];
+ }
+ if ($good_pos > $bad_pos) {
+ return 0;
+ }
+ return 1;
+}
sub cppflags_fortify_broken {
my ($line, $missing_flags) = @_;
- # This doesn't take the position into account, but is a simple solution.
- # And if the build system tries to force -D_FORTIFY_SOURCE=0/1, something
- # is wrong anyway.
+ # $def_cppflags_fortify[0] must be -D_FORTIFY_SOURCE=2!
+ my $fortify_source = $def_cppflags_fortify[0];
- if (any_flags_used($line, @def_cppflags_fortify_bad)) {
- # $def_cppflags_fortify[0] must be -D_FORTIFY_SOURCE=2!
- push @{$missing_flags}, $def_cppflags_fortify[0];
- return 1;
+ # Some build systems enable/disable fortify source multiple times, check
+ # the final result.
+ if (not flag_overwritten($line,
+ $fortify_source,
+ \@def_cppflags_fortify_bad)) {
+ return 0;
}
+ push @{$missing_flags}, $fortify_source;
+ return 1;
+}
- return 0;
+sub cflags_stack_broken {
+ my ($line, $missing_flags, $strong) = @_;
+
+ my $flag = $strong ? $def_cflags_stack_strong[0]
+ : $def_cflags_stack[0];
+
+ if (not flag_overwritten($line, $flag, \@def_cflags_stack_bad)) {
+ return 0;
+ }
+ push @{$missing_flags}, $flag;
+ return 1;
}
# Modifies $missing_flags_ref array.
# This flags is not always available, but if it is use it.
if ($line =~ /^DEB_BUILD_OPTIONS=.*\bparallel=(\d+)/) {
- $parallel = $1;
+ $parallel = $1 * 2;
}
# We skip over unimportant lines at the beginning of the log to
# Option or auto detected.
if ($arch) {
- # The following was partially copied from dpkg-dev 1.18.24
- # (/usr/share/perl5/Dpkg/Vendor/Debian.pm, _add_hardening_flags()),
- # copyright Raphaël Hertzog <hertzog@debian.org>, Kees Cook
- # <kees@debian.org>, Canonical, Ltd. licensed under GPL version 2 or
- # later. Keep it in sync.
+ # The following was partially copied from dpkg-dev 1.19.0.5
+ # (/usr/share/perl5/Dpkg/Vendor/Debian.pm, _add_build_flags()),
+ # copyright Raphaël Hertzog <hertzog@debian.org>, Guillem Jover
+ # <guillem@debian.org>, Kees Cook <kees@debian.org>, Canonical, Ltd.
+ # licensed under GPL version 2 or later. Keep it in sync.
require Dpkg::Arch;
my ($os, $cpu);
}
my %builtin_pie_arch = map { $_ => 1 } qw(
- amd64 arm64 armel armhf i386 kfreebsd-amd64 kfreebsd-i386
- mips mipsel mips64el ppc64el s390x sparc sparc64
+ amd64 arm64 armel armhf hurd-i386 i386 kfreebsd-amd64 kfreebsd-i386
+ mips mipsel mips64el powerpc ppc64 ppc64el s390x sparc sparc64
);
# Disable unsupported hardening options.
# Check hardening flags.
my @missing;
- if ($compile and not all_flags_used($line, \@missing, @cflags)
+ if ($compile and (not all_flags_used($line, \@missing, @cflags)
+ or (($harden_stack or $harden_stack_strong)
+ and cflags_stack_broken($line, \@missing,
+ $harden_stack_strong)))
# Libraries linked with -fPIC don't have to (and can't) be
# linked with -fPIE as well. It's no error if only PIE flags
# are missing.