X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=bin%2Fblhc;h=123613817a50af16c7b27c35b8c1fb7264d27f4a;hb=0e29a93fc2056d254ef650e81d9299a62bfc13b3;hp=e183027e22886699b7e4c66639ad77c12555034e;hpb=d9bd7570d07a93026a3147971c8e34be6c1c6c86;p=blhc%2Fblhc.git diff --git a/bin/blhc b/bin/blhc index e183027..1236138 100755 --- a/bin/blhc +++ b/bin/blhc @@ -31,8 +31,8 @@ our $VERSION = '0.01'; # CONSTANTS/VARIABLES # Regex to catch compiler commands. -my $cc_regex = qr/(?:[a-z0-9_]+-(?:linux|kfreebsd)-gnu(?:eabi|eabihf)?-)? - (?:(? '-Wl,-z,now', ); +# Use colored (ANSI) output? +my $option_color; + # FUNCTIONS @@ -180,11 +183,16 @@ sub error_non_verbose_build { error_color(':', 'yellow'), $line; } +sub error_hardening_wrapper { + printf "%s%s %s\n", + error_color('HARDENING WRAPPER', 'red'), + error_color(':', 'yellow'), + 'no checks possible, aborting'; +} sub error_color { my ($message, $color) = @_; - # Use colors when writing to a terminal. - if (-t STDOUT) { + if ($option_color) { return Term::ANSIColor::colored($message, $color); } else { return $message; @@ -294,6 +302,7 @@ my $option_version = 0; my $option_all = 0; my $option_arch = undef; my $option_buildd = 0; + $option_color = 0; if (not Getopt::Long::GetOptions( 'help|h|?' => \$option_help, 'version' => \$option_version, @@ -302,6 +311,7 @@ if (not Getopt::Long::GetOptions( 'bindnow' => \$harden_bindnow, 'all' => \$option_all, # Misc. + 'color' => \$option_color, 'arch' => \$option_arch, 'buildd' => \$option_buildd, )) { @@ -366,10 +376,22 @@ while (my $line = <>) { } } + # If hardening wrapper is used (wraps calls to gcc and adds hardening + # flags automatically) we can't perform any checks, abort. + if (not $start and $line =~ /^Build-Depends: .*\bhardening-wrapper\b/) { + error_hardening_wrapper(); + $exit |= 1 << 4; + exit $exit; + } + # We skip over unimportant lines at the beginning of the log to prevent # false positives. $start = 1 if $line =~ /^dpkg-buildpackage:/; next if not $start; + # And stop at the end of the build log. Package details (reported by the + # buildd logs) are not important for us. This also prevents false + # positives. + last if $line =~ /^Build finished at \d{8}-\d{4}$/; # Detect architecture automatically unless overridden. if (not $option_arch @@ -434,7 +456,8 @@ while (my $line = <>) { # Ignore false positives. # # `./configure` output. - next if not $non_verbose and $line =~ /^checking /; + next if not $non_verbose + and $line =~ /^(?:checking|(?:C|c)onfigure:) /; next if $line =~ /^\s*(?:Host\s+)?(?:C\s+)? (?:C|c)ompiler[\s.]*:?\s+ $cc_regex @@ -443,10 +466,11 @@ while (my $line = <>) { or $line =~ /^\s*(?:- )?(?:HOST_)?(?:CC|CXX)\s*=\s*$cc_regex\s*$/ or $line =~ /^\s*-- Check for working (?:C|CXX) compiler: / or $line =~ /^\s*(?:echo )?Using [A-Z_]+\s*=\s*/; - # Debian buildd output. - next if $line =~ /^\s*Depends: .*?$cc_regex.*?$/ - and $line !~ /\s-./; # option, prevent false negatives + # Check if additional hardening options were used. Used to ensure + # they are used for the complete build. + $harden_pie = 1 if any_flags_used($line, @cflags_pie, @ldflags_pie); + $harden_bindnow = 1 if any_flags_used($line, @ldflags_bindnow); push @input, $line; } @@ -480,13 +504,6 @@ if ($option_arch) { } } -# Check if additional hardening options were used. Used to ensure they are -# used for the complete build. -foreach my $line (@input) { - $harden_pie = 1 if any_flags_used($line, @cflags_pie, @ldflags_pie); - $harden_bindnow = 1 if any_flags_used($line, @ldflags_bindnow); -} - # Check the specified hardening options, same order as dpkg-buildflags. if ($harden_pie) { @cflags = (@cflags, @cflags_pie); @@ -566,17 +583,23 @@ for (my $i = 0; $i < scalar @input; $i++) { if ($compile and not all_flags_used($line, \@missing, @cflags) # 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. - and not pic_pie_conflict($line, $harden_pie, \@missing, @cflags_pie)) { + and not pic_pie_conflict($line, $harden_pie, \@missing, @cflags_pie) + # Assume dpkg-buildflags returns the correct flags. + and not $line =~ /`dpkg-buildflags --get (?:CFLAGS|CXXFLAGS)`/) { error_flags('CFLAGS missing', \@missing, \%flag_renames, $line); $exit |= 1 << 3; } - if ($preprocess and not all_flags_used($line, \@missing, @cppflags)) { + if ($preprocess and not all_flags_used($line, \@missing, @cppflags) + # Assume dpkg-buildflags returns the correct flags. + and not $line =~ /`dpkg-buildflags --get CPPFLAGS`/) { error_flags('CPPFLAGS missing', \@missing, \%flag_renames, $line); $exit |= 1 << 3; } if ($link and not all_flags_used($line, \@missing, @ldflags) # Same here, -fPIC conflicts with -fPIE. - and not pic_pie_conflict($line, $harden_pie, \@missing, @ldflags_pie)) { + and not pic_pie_conflict($line, $harden_pie, \@missing, @ldflags_pie) + # Assume dpkg-buildflags returns the correct flags. + and not $line =~ /`dpkg-buildflags --get LDFLAGS`/) { error_flags('LDFLAGS missing', \@missing, \%flag_renames, $line); $exit |= 1 << 3; } @@ -593,9 +616,7 @@ blhc - build log hardening check, checks build logs for missing hardening flags =head1 SYNOPSIS -B [-h -? --help] - -B [--pie] [--bindnow] [--all] +B [options] --help available options --version version number and license @@ -604,6 +625,7 @@ B [--pie] [--bindnow] [--all] --all force +all (+pie, +bindnow) check --arch set architecture (autodetected) --buildd parser mode for buildds + --color use colored output =head1 DESCRIPTION @@ -655,6 +677,10 @@ detected). =back +=item B<--color> + +Use colored (ANSI) output for warning messages. + =back Auto detection for B<--pie> and B<--bindnow> only works if at least one @@ -666,7 +692,7 @@ all other commands as well. The exit status is a "bit mask", each listed status is ORed when the error condition occurs to get the result. -=over 8 +=over 4 =item B<0> @@ -688,6 +714,10 @@ Non verbose build. Missing hardening flags. +=item B<16> + +Hardening wrapper detected, no tests performed. + =back =head1 AUTHOR