]> ruderich.org/simon Gitweb - blhc/blhc.git/blobdiff - bin/blhc
Add missing //o to regex
[blhc/blhc.git] / bin / blhc
index fb4123c9d4ed5067a319dec9804a30c0fe09463b..193297e4b7fdba4ffb6095074b4c3cea0774e055 100755 (executable)
--- a/bin/blhc
+++ b/bin/blhc
@@ -24,7 +24,7 @@ use warnings;
 use Getopt::Long ();
 use Text::ParseWords ();
 
-our $VERSION = '0.07';
+our $VERSION = '0.08';
 
 
 # CONSTANTS/VARIABLES
@@ -222,11 +222,17 @@ my @def_cflags_fortify = (
     # 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',
@@ -270,6 +276,7 @@ my @flag_refs = (
     \@def_cflags_fortify,
     \@def_cflags_stack,
     \@def_cflags_stack_strong,
+    \@def_cflags_stack_bad,
     \@def_cflags_pie,
     \@def_cxxflags,
     \@def_cppflags,
@@ -427,21 +434,61 @@ sub all_flags_used {
     @{$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.
@@ -872,7 +919,7 @@ foreach my $file (@ARGV) {
 
         # 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
@@ -1026,7 +1073,7 @@ foreach my $file (@ARGV) {
             # treated as a normal compiler line.
             next if $line =~ m{^\s*rm\s+};
             # Some build systems emit "gcc > file".
-            next if $line =~ m{$cc_regex_normal\s*>\s*\S+};
+            next if $line =~ m{$cc_regex_normal\s*>\s*\S+}o;
 
             # Check if additional hardening options were used. Used to ensure
             # they are used for the complete build.
@@ -1068,11 +1115,11 @@ foreach my $file (@ARGV) {
 
     # 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);
@@ -1085,8 +1132,8 @@ foreach my $file (@ARGV) {
         }
 
         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.
@@ -1329,7 +1376,10 @@ LINE:
 
         # 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.