X-Git-Url: https://ruderich.org/simon/gitweb/?p=blhc%2Fblhc.git;a=blobdiff_plain;f=bin%2Fblhc;h=3b7f746113c319484b10f900f7c1fa50228d8e29;hp=0892cad25e345f0c830c58a929b4b54ebbac73f3;hb=a4712dd7fab2e1e14ba27894279dc793d1944536;hpb=0798b6d8fc65dd5fe2a975789dea153a96dcac89 diff --git a/bin/blhc b/bin/blhc index 0892cad..3b7f746 100755 --- a/bin/blhc +++ b/bin/blhc @@ -2,7 +2,7 @@ # Build log hardening check, checks build logs for missing hardening flags. -# Copyright (C) 2012-2019 Simon Ruderich +# Copyright (C) 2012-2020 Simon Ruderich # # 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 @@ -24,7 +24,7 @@ use warnings; use Getopt::Long (); use Text::ParseWords (); -our $VERSION = '0.09'; +our $VERSION = '0.11'; # CONSTANTS/VARIABLES @@ -53,7 +53,7 @@ my $cc_regex_normal = qr/ my $warning_regex = qr/^(.+?):(\d+):\d+: warning: (.+?) \[(.+?)\]$/; # Regex to catch libtool commands and not lines which show commands executed # by libtool (e.g. libtool: link: ...). -my $libtool_regex = qr/\blibtool\s.*--mode=/; +my $libtool_regex = qr/\blibtool["']?\s.*--mode=/; my $libtool_link_regex = qr/\blibtool: link: /; # List of source file extensions which require preprocessing. @@ -532,7 +532,7 @@ sub is_non_verbose_build { if (not (index($line, 'checking if you want to see long compiling messages... no') == 0 or $line =~ /^\s*\[?(?:CC|CCLD|C\+\+|CXX|CXXLD|LD|LINK)\]?\s+(.+?)$/ - or $line =~ /^\s*[Cc]ompiling\s+(.+?)(?:\.\.\.)?$/ + or $line =~ /^\s*[][\/0-9 ]*[Cc]ompiling\s+(.+?)(?:\.\.\.)?$/ or $line =~ /^\s*[Bb]uilding (?:program|shared library)\s+(.+?)$/ or $line =~ /^\s*\[[\d ]+%\] Building (?:C|CXX) object (.+?)$/)) { return 0; @@ -544,7 +544,7 @@ sub is_non_verbose_build { return 0 if $line =~ /^\s*C\+\+.+?:\s+(?:yes|no)\s*$/; return 0 if $line =~ /^\s*C\+\+ Library: stdc\+\+$/; # "Compiling" non binary files. - return 0 if $line =~ /^\s*Compiling \S+\.(?:py|el)['"]?\s*(?:\.\.\.)?$/; + return 0 if $line =~ /^\s*Compiling \S+\.(?:py|pyx|el)['"]?\s*(?:\.\.\.|because it changed\.)?$/; return 0 if $line =~ /^\s*[Cc]ompiling catalog \S+\.po\b/; # "Compiling" with no file name. if ($line =~ /^\s*[Cc]ompiling\s+(.+?)(?:\.\.\.)?$/) { @@ -684,7 +684,7 @@ if ($option_help) { } if ($option_version) { print <<"EOF"; -blhc $VERSION Copyright (C) 2012-2019 Simon Ruderich +blhc $VERSION Copyright (C) 2012-2020 Simon Ruderich 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 @@ -750,6 +750,7 @@ foreach my $flags (@flag_refs_all) { } # Precompile ignore line regexps, also anchor at beginning and end of line. +# Additional entries are also extracted from the build log, see below. foreach my $ignore (@option_ignore_line) { $ignore = qr/^$ignore$/; } @@ -792,13 +793,6 @@ foreach my $file (@ARGV) { my $harden_bindnow = $option_bindnow; # defaults to 0 my $harden_pie = $option_pie; # defaults to 0 - # Does this build log use ada? Ada also uses gcc as compiler but uses - # different CFLAGS. But only perform ada checks if an ada compiler is used - # for performance reasons. - my $ada = 0; - # Fortran also requires different CFLAGS. - my $fortran = 0; - # Number of parallel jobs to prevent false positives when detecting # non-verbose builds. As not all jobs declare the number of parallel jobs # use a large enough default. @@ -907,15 +901,6 @@ foreach my $file (@ARGV) { } next FILE; } - - # Ada compiler. - if ($line =~ /\bgnat\b/) { - $ada = 1; - } - # Fortran compiler. - if ($line =~ /\bgfortran\b/) { - $fortran = 1; - } } # This flags is not always available, but if it is use it. @@ -970,6 +955,15 @@ foreach my $file (@ARGV) { } } + # Permit dynamic excludes from within the build log to ignore false + # positives. Cannot use a separate config file as we often only have + # the build log itself. + if (index($line, 'blhc: ignore-line-regexp: ') == 0) { + my $ignore = substr $line, 26, -1; # -1 to ignore '\n' at the end + push @option_ignore_line, qr/^$ignore$/; + next; + } + next if $line =~ /^\s*#/; # Ignore compiler warnings for now. next if $line =~ /$warning_regex/o; @@ -1077,10 +1071,15 @@ foreach my $file (@ARGV) { # look like a compiler executable thus causing the line to be # treated as a normal compiler line. next if $line =~ m{^\s*rm\s+}; + next if $line =~ m{^\s*dwz\s+}; # Some build systems emit "gcc > file". next if $line =~ m{$cc_regex_normal\s*>\s*\S+}o; # Hex output may contain "cc". next if $line =~ m#(?:\b[0-9a-fA-F]{2,}\b\s*){5}#; + # Meson build output + next if $line =~ /^C\+\+ linker for the host machine: /; + # Embedded `gcc -print-*` commands + next if $line =~ /`$cc_regex_normal\s*[^`]*-print-\S+`/; # Check if additional hardening options were used. Used to ensure # they are used for the complete build. @@ -1122,7 +1121,7 @@ foreach my $file (@ARGV) { # Option or auto detected. if ($arch) { - # The following was partially copied from dpkg-dev 1.19.7 + # The following was partially copied from dpkg-dev 1.20.5 # (/usr/share/perl5/Dpkg/Vendor/Debian.pm, _add_build_flags()), # copyright Raphaël Hertzog , Guillem Jover # , Kees Cook , Canonical, Ltd. @@ -1213,19 +1212,15 @@ foreach my $file (@ARGV) { } # Ada doesn't support format hardening flags, see #680117 for more - # information. Same for fortran. Filter them out if either language is - # used. + # information. Same for fortran. my @cflags_backup; - my @cflags_noformat; - if (($ada or $fortran) and $harden_format) { - @cflags_noformat = grep { - my $ok = 1; - foreach my $flag (@def_cflags_format) { - $ok = 0 if $_ eq $flag; - } - $ok; - } @cflags; - } + my @cflags_noformat = grep { + my $ok = 1; + foreach my $flag (@def_cflags_format) { + $ok = 0 if $_ eq $flag; + } + $ok; + } @cflags; # Hack to fix cppflags_fortify_broken() if --ignore-flag # -D_FORTIFY_SOURCE=2 is used to ignore missing fortification. Only works @@ -1367,16 +1362,14 @@ LINE: and extension_found(\%extensions_compile_cpp, @extensions)) { $compile = 0; $compile_cpp = 1; - # Ada needs special CFLAGS, use them if only ada files are compiled. - } elsif ($ada - and extension_found(\%extensions_ada, @extensions)) { + # Ada needs special CFLAGS + } elsif (extension_found(\%extensions_ada, @extensions)) { $restore_cflags = 1; $preprocess = 0; # Ada uses no CPPFLAGS @cflags_backup = @cflags; @cflags = @cflags_noformat; - # Same for fortran. - } elsif ($fortran - and extension_found(\%extensions_fortran, @extensions)) { + # Same for fortran + } elsif (extension_found(\%extensions_fortran, @extensions)) { $restore_cflags = 1; @cflags_backup = @cflags; @cflags = @cflags_noformat; @@ -1535,6 +1528,22 @@ If there's no output, no flags are missing and the build log is fine. See F for details about performed checks, auto-detection and limitations. +=head1 FALSE POSITIVES + +To suppress false positives you can embed the following string in the build +log: + + blhc: ignore-line-regexp: REGEXP + +All lines fully matching REGEXP (see B<--ignore-line> for details) will be +ignored. + +Please use this feature sparingly so that missing flags are not overlooked. If +you find false positives which affect more packages please report a bug. + +To generate this string simply use echo in C; make sure to use @ +to suppress the echo command itself as it could also trigger a false positive. + =head1 OPTIONS =over 8 @@ -1780,7 +1789,7 @@ Ejari.aalto@cante.netE for their valuable input and suggestions. =head1 LICENSE AND COPYRIGHT -Copyright (C) 2012-2019 by Simon Ruderich +Copyright (C) 2012-2020 by Simon Ruderich 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