[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 2.5.6-60-g33acfe7



The following commit has been merged in the master branch:
commit d44806c01bc074364c6f422d8dbeeaec74b4d27e
Author: Kees Cook <kees@outflux.net>
Date:   Thu Dec 1 16:04:00 2011 -0800

    Add initial lintian checks for ELF hardening
    
    This adds the "hardening-info" collector which depends on the
    new "--lintian" mode of the "hardening-check" tool found in the
    "hardening-includes" package.
    
    Signed-off-by: Kees Cook <kees@debian.org>
    
    Changes to the original patch:
      * Give hardening tags a common prefix in their names
      * Remove hardening-no-bindnow and hardening-no-format tags
      * Minor test clean up
    
    Signed-off-by: Niels Thykier <niels@thykier.net>

diff --git a/checks/binaries b/checks/binaries
index faa4b8b..d5842b5 100644
--- a/checks/binaries
+++ b/checks/binaries
@@ -1,6 +1,7 @@
 # binaries -- lintian check script -*- perl -*-
 
 # Copyright (C) 1998 Christian Schwarz and Richard Braakman
+# Copyright (C) 2012 Kees Cook
 #
 # 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
@@ -429,6 +430,15 @@ foreach my $file (@{$info->sorted_index}) {
                 tag 'program-not-linked-against-libc', $file;
             }
         }
+
+        # Check for missing hardening characteristics. This currently
+        # handles the following checks:
+        # no-relro no-fortify-functions no-stackprotector no-bindnow no-pie
+        if (exists($info->hardening_info->{$file})) {
+            foreach my $tag (@{$info->hardening_info->{$file}}) {
+                tag "hardening-$tag", $file;
+            }
+        }
     }
 }
 
diff --git a/checks/binaries.desc b/checks/binaries.desc
index 4e0ad1e..fe5fed7 100644
--- a/checks/binaries.desc
+++ b/checks/binaries.desc
@@ -2,7 +2,7 @@ Check-Script: binaries
 Author: Christian Schwarz <schwarz@debian.org>
 Abbrev: bin
 Type: binary, udeb
-Needs-Info: objdump-info, file-info, strings, index
+Needs-Info: hardening-info, objdump-info, file-info, strings, index
 Info: This script checks binaries and object files for bugs.
 
 Tag: arch-independent-package-contains-binary-or-object
@@ -299,3 +299,36 @@ Info: This package provides an OCaml bytecode executable linked with a
  custom runtime. Such executables cannot be stripped and require
  special care. Their usage is deprecated in favour of shared libraries
  for C stubs (dll*.so).
+
+Tag: hardening-no-stackprotector
+Severity: normal
+Certainty: possible
+Info: This package provides an ELF binary that lacks the stack protector
+ function <tt>__stack_chk_fail</tt>. Either there are no character arrays used
+ on the stack of any routines, or the package was not built with the
+ default Debian compiler flags defined by <tt>dpkg-buildflags</tt>. If built
+ using <tt>dpkg-buildflags</tt> directly, be sure to import <tt>CFLAGS</tt>
+ and/or <tt>CXXFLAGS</tt>.
+Ref: http://wiki.debian.org/Hardening
+
+Tag: hardening-no-fortify-functions
+Severity: normal
+Certainty: possible
+Info: This package provides an ELF binary that lacks the use of fortified
+ libc functions. Either there are no potentially unfortified functions
+ called by any routines, all unfortified calls have already been fully
+ validated at compile-time, or the package was not built with the default
+ Debian compiler flags defined by <tt>dpkg-buildflags</tt>. If built using
+ <tt>dpkg-buildflags</tt> directly, be sure to import <tt>CPPFLAGS</tt>.
+Ref: http://wiki.debian.org/Hardening
+
+Tag: hardening-no-relro
+Severity: normal
+Certainty: certain
+Info: This package provides an ELF binary that lacks the "read-only
+ relocation" link flag. This package was likely not built with the
+ default Debian compiler flags defined by <tt>dpkg-buildflags</tt>.
+ If built using <tt>dpkg-buildflags</tt> directly, be sure to import
+ <tt>LDFLAGS</tt>.
+Ref: http://wiki.debian.org/Hardening
+
diff --git a/collection/hardening-info b/collection/hardening-info
new file mode 100755
index 0000000..c8e49d0
--- /dev/null
+++ b/collection/hardening-info
@@ -0,0 +1,98 @@
+#!/usr/bin/perl -w
+# hardening-info -- lintian collection script
+
+# The original shell script version of this script is
+# Copyright (C) 1998 Christian Schwarz
+#
+# The objdump version, including support for etch's binutils, is
+# Copyright (C) 2008 Adam D. Barratt
+#
+# This version, a trimmed-down wrapper for hardening-check, is
+# Copyright (C) 2012 Kees Cook <kees@debian.org>
+#
+# 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
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+use strict;
+use warnings;
+
+use lib "$ENV{'LINTIAN_ROOT'}/lib";
+use Util;
+use Cwd;
+
+open (OUT, '>', 'hardening-info')
+    or fail("cannot open hardening-info: $!");
+
+# If we're running inside the Lintian test suite itself, we need to avoid
+# all the tests except the "binaries-hardening" test.
+my $base = Cwd::realpath('.');
+exit 0
+    if (defined $ENV{'LINTIAN_INTERNAL_TESTSUITE'} and
+        $ENV{'LINTIAN_INTERNAL_TESTSUITE'} eq "1" and
+        $base !~ m|/binaries-hardening/binaries-hardening_1.0_.*_binary$|);
+
+open (FILES, '<', 'file-info')
+    or fail("cannot open file-info: $!");
+
+# Override the arch seen by dpkg-buildflags for the arch of this package.
+my @fields = read_dpkg_control ('control/control');
+defined ($fields[0]{'architecture'})
+    or fail ("cannot determine architecture of package!");
+$ENV{'DEB_HOST_ARCH'} = $fields[0]{'architecture'}
+    if ($fields[0]{'architecture'} ne "all");
+
+# Prepare to examine the file tree.
+chdir ('unpacked')
+    or fail("unable to chdir to unpacked: $!");
+
+# We must figure out what hardening features are expected by default for a
+# given architecture. Extract this from "dpkg-buildflags", and set up the
+# needed arguments for calling "hardening-check".
+open (my $FLAGS, '-|', "dpkg-buildflags --query-features hardening")
+    or fail ("could not launch dpkg-buildflags: $!");
+my $args = "--lintian";
+my $feature = "";
+@fields = parse_dpkg_control ($FLAGS);
+foreach my $flag (@fields) {
+    if ($flag->{enabled} eq "no") {
+        $args .= " --no" . $flag->{feature};
+    }
+}
+close $FLAGS;
+
+while (<FILES>) {
+    if (m/^(.+?)\x00\s.*ELF/) {
+        my $bin = $1;
+
+        if (open (PIPE, '-|', "hardening-check $args -- \Q$bin\E 2>&1")) {
+            local $/;
+            local $_ = <PIPE>;
+            print OUT $_;
+            close PIPE;
+        }
+    }
+}
+
+close FILES;
+close OUT or fail("cannot write objdump-info: $!");
+
+exit 0;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 sr et
diff --git a/collection/hardening-info.desc b/collection/hardening-info.desc
new file mode 100644
index 0000000..ee051fe
--- /dev/null
+++ b/collection/hardening-info.desc
@@ -0,0 +1,7 @@
+Collector-Script: hardening-info
+Author: Kees Cook <kees@debian.org>
+Info: This script runs hardening-check(1) over all ELF binaries of a binary
+ package.
+Type: binary, udeb
+Version: 1
+Needs-Info: bin-pkg-control, file-info, unpacked
diff --git a/debian/changelog b/debian/changelog
index 99cf292..c0798b7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -11,6 +11,9 @@ lintian (2.5.7) UNRELEASED; urgency=low
       - debian-control-with-duplicate-fields
       - doc-base-file-references-usr-doc
       - duplicate-fields-in-templates
+      - hardening-no-fortify-functions
+      - hardening-no-relro
+      - hardening-no-stackprotector
       - manpage-for-non-x11-binary-in-wrong-directory
       - manpage-for-x11-binary-in-wrong-directory
       - obsolete-field
@@ -28,8 +31,10 @@ lintian (2.5.7) UNRELEASED; urgency=low
     + [NT] Remove some old tags that are no longer useful.
       (Closes: #663516)
     + [NT] Migrate to sorted_index from sorted_file_info.
-  * checks/binaries:
+  * checks/binaries{,.desc}:
     + [NT] Move embedded library data to a data file.
+    + [NT] Add ELF hardening checks.  Thanks to Kees Cook for
+      report and the patches.  (Closes: 650536)
   * checks/changes-file{,.desc}:
     + [NT] Remove Ubuntu specific handling of distribution names.
       Instead replace it with a more generalized one that derivatives
@@ -72,6 +77,8 @@ lintian (2.5.7) UNRELEASED; urgency=low
       bin-pkg-control.
   * collection/file-info{,.desc}:
     + [NT] Compress file-info output and bump version of file-info.
+  * collection/hardening-info{,.desc}:
+    + [NT] New files.  Thanks to Kees Cook for the patch.
   * collection/index{,.desc}:
     + [NT] Compress index output and bump version of index.
   * collection/objdump-info:
diff --git a/debian/control b/debian/control
index 24be849..6967aae 100644
--- a/debian/control
+++ b/debian/control
@@ -16,9 +16,11 @@ Build-Depends: binutils,
                diffstat,
                docbook-utils,
                docbook-xml,
+               dpkg-dev (>= 1.16.2~wipmultiarch),
                fakeroot,
                file,
                gettext,
+               hardening-includes (>= 1.35),
                intltool-debian,
                javahelper (>= 0.32~),
                libapt-pkg-perl,
@@ -60,8 +62,10 @@ Architecture: all
 Depends: binutils,
          bzip2,
          diffstat,
+         dpkg-dev (>= 1.16.2~wipmultiarch),
          file,
          gettext,
+         hardening-includes (>= 1.35),
          intltool-debian,
          libapt-pkg-perl,
          libc-bin (>= 2.13) | locales,
@@ -80,7 +84,6 @@ Depends: binutils,
          unzip,
          ${misc:Depends}
 Suggests: binutils-multiarch,
-          dpkg-dev,
           libhtml-parser-perl,
           libtext-template-perl,
           man-db (>= 2.5.1-1),
diff --git a/lib/Lintian/Collect/Binary.pm b/lib/Lintian/Collect/Binary.pm
index 0c50326..6098eec 100644
--- a/lib/Lintian/Collect/Binary.pm
+++ b/lib/Lintian/Collect/Binary.pm
@@ -3,6 +3,7 @@
 
 # Copyright (C) 2008, 2009 Russ Allbery
 # Copyright (C) 2008 Frank Lichtenheld
+# Copyright (C) 2012 Kees Cook
 #
 # 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
@@ -227,6 +228,32 @@ sub objdump_info {
 }
 
 
+# Returns the information from collect/hardening-info
+# sub hardening_info Needs-Info hardening-info
+sub hardening_info {
+    my ($self) = @_;
+    return $self->{hardening_info} if exists $self->{hardening_info};
+    my $base_dir = $self->base_dir();
+    my %hardening_info;
+    my ($file);
+    open(my $idx, '<', "$base_dir/hardening-info")
+        or fail("cannot open $base_dir/hardening-info: $!");
+    while (<$idx>) {
+        chomp;
+
+        if (m,^([^:]+):\./(.*)$,) {
+            my ($tag, $file) = ($1, $2);
+
+            push(@{$hardening_info{$file}}, $tag);
+        }
+    }
+
+    $self->{hardening_info} = \%hardening_info;
+
+    return $self->{hardening_info};
+}
+
+
 # Returns the information from collect/objdump-info
 # sub java_info Needs-Info java-info
 sub java_info {
diff --git a/t/scripts/implemented-tags.t b/t/scripts/implemented-tags.t
index 2575748..8672416 100755
--- a/t/scripts/implemented-tags.t
+++ b/t/scripts/implemented-tags.t
@@ -42,6 +42,7 @@ our $EXCLUDE =
                  ^example.*interpreter.*
                  ^example-script-.*$
                  ^example-shell-script-.*$
+                 ^hardening-.*$
                 ));
 
 # Find all of the check description files.  We'll do one check per
diff --git a/t/tests/binaries-hardening/debian/Makefile b/t/tests/binaries-hardening/debian/Makefile
new file mode 100644
index 0000000..40ce958
--- /dev/null
+++ b/t/tests/binaries-hardening/debian/Makefile
@@ -0,0 +1,24 @@
+all: weak.1 strong.1
+	# Build without dpkg-buildflags.
+	gcc -o weak hello.c
+	gcc -o strong \
+		$(shell dpkg-buildflags --get CPPFLAGS) \
+		$(shell dpkg-buildflags --get CFLAGS) \
+		$(shell dpkg-buildflags --get LDFLAGS) \
+		hello.c
+%.1: base.pod
+	sed s/@NAME@/$(basename $@)/g < $< | \
+	   pod2man --name $(basename $@) --section 1 > $@
+
+install:
+	install -d $(DESTDIR)/usr/bin/
+	install -d $(DESTDIR)/usr/share/man/man1
+	install -m 755 -c weak $(DESTDIR)/usr/bin/weak
+	install -m 755 -c strong $(DESTDIR)/usr/bin/strong
+	install -m 644 -c weak.1 $(DESTDIR)/usr/share/man/man1/weak.1
+	install -m 644 -c strong.1 $(DESTDIR)/usr/share/man/man1/strong.1
+
+clean distclean:
+	rm -f weak strong *.1
+
+check test:
diff --git a/t/tests/binaries-hardening/debian/base.pod b/t/tests/binaries-hardening/debian/base.pod
new file mode 100644
index 0000000..1e900d7
--- /dev/null
+++ b/t/tests/binaries-hardening/debian/base.pod
@@ -0,0 +1,12 @@
+=head1 NAME
+
+@NAME@ -- binary that does something
+
+=head1 SYNOPSIS
+
+ @NAME@ [options]
+
+=head1 DESCRIPTION
+
+@NAME@ does something very useful.
+
diff --git a/t/tests/binaries-hardening/debian/hello.c b/t/tests/binaries-hardening/debian/hello.c
new file mode 100644
index 0000000..7b87bd7
--- /dev/null
+++ b/t/tests/binaries-hardening/debian/hello.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+void
+report(char *string)
+{
+    char buf[80];
+    int len;
+
+    strcpy(buf, string);
+    fprintf(stdout, "Hello world from %s!\n%n", buf, &len);
+}
+
+int
+main(int argc, char *argv[])
+{
+    report(argv[0]);
+}
diff --git a/t/tests/binaries-hardening/desc b/t/tests/binaries-hardening/desc
new file mode 100644
index 0000000..ad18843
--- /dev/null
+++ b/t/tests/binaries-hardening/desc
@@ -0,0 +1,9 @@
+Testname: binaries-hardening
+Sequence: 6000
+Version: 1.0
+Description: Check for missing hardening features
+Architecture: amd64 i386
+Test-For:
+ hardening-no-relro
+ hardening-no-stackprotector
+ hardening-no-fortify-functions
diff --git a/t/tests/binaries-hardening/tags b/t/tests/binaries-hardening/tags
new file mode 100644
index 0000000..ec90777
--- /dev/null
+++ b/t/tests/binaries-hardening/tags
@@ -0,0 +1,3 @@
+W: binaries-hardening: hardening-no-fortify-functions usr/bin/weak
+W: binaries-hardening: hardening-no-relro usr/bin/weak
+W: binaries-hardening: hardening-no-stackprotector usr/bin/weak

-- 
Debian package checker


Reply to: