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

[SCM] Debian package checker branch, squeeze, updated. 2.4.3-16-gddd5248



The following commit has been merged in the squeeze branch:
commit f8789fa30740be704d5d04d69d8a38e259e4525d
Author: Niels Thykier <niels@thykier.net>
Date:   Fri Apr 5 16:20:14 2013 +0200

    checks/*: Check for symlinks before opening files
    
    Signed-off-by: Niels Thykier <niels@thykier.net>

diff --git a/checks/cruft b/checks/cruft
index 34ab8d9..05e2ad2 100644
--- a/checks/cruft
+++ b/checks/cruft
@@ -313,6 +313,10 @@ sub find_cruft {
         }
     }
     -f or return; # we just need normal files for the rest
+    if (-l && !is_ancestor_of($info->unpacked, $_)) {
+        # skip unsafe symlinks too
+        return;
+    }
 
     unless ($warned->{$name}) {
         for my $rule (@file_checks) {
diff --git a/checks/debhelper b/checks/debhelper
index 56bbc00..54c9a2d 100644
--- a/checks/debhelper
+++ b/checks/debhelper
@@ -70,10 +70,16 @@ my $seendhcleank = '';
 my $overridetargets = 0;
 my %missingbdeps;
 
+if ( ! -f "debfiles/rules" or !is_ancestor_of("debfiles", "debfiles/rules")) {
+    # unsafe symlink
+    return;
+}
+
 open(RULES, '<', "debfiles/rules") or fail("cannot read debian/rules: $!");
 my $maybe_skipping;
 my $dhcompatvalue;
 my @versioncheck;
+
 while (<RULES>) {
     if (/^ifn?(eq|def)\s/) {
         $maybe_skipping++;
@@ -244,6 +250,7 @@ opendir(DEBIAN, 'debfiles')
 while (defined(my $file=readdir(DEBIAN))) {
     if ($file =~ m/^(?:(.*)\.)?(?:post|pre)(?:inst|rm)$/) {
 	next unless $needtomodifyscripts;
+	next unless is_ancestor_of("debfiles", "debfiles/$file");
 
 	# They need to have #DEBHELPER# in their scripts.  Search for scripts
 	# that look like maintainer scripts and make sure the token is there.
@@ -310,6 +317,8 @@ while (defined(my $file=readdir(DEBIAN))) {
 	# supported.
 	if ($filename_configs->known($base)) {
 	    next if $level < 3;
+	    next unless is_ancestor_of("debfiles", "debfiles/$file");
+
 	    open (IN, '<', "debfiles/$file")
 		or fail("Can't open debfiles/$file: $!");
 	    local $_;
diff --git a/checks/infofiles b/checks/infofiles
index 2c5b994..1bb8061 100644
--- a/checks/infofiles
+++ b/checks/infofiles
@@ -87,6 +87,10 @@ foreach my $file (sort keys %{$info->index}) {
     # If this is the main info file (no numeric extension). make sure it has
     # appropriate dir entry information.
     if ($fname !~ /-\d+\.gz/ && $file_info =~ /gzip compressed data/) {
+        if ($index_info->{type} eq 'l' && !is_ancestor_of("unpacked", $file)) {
+            # unsafe symlink, skip
+            next;
+        }
 	my $pid = open INFO, '-|';
 	if (not defined $pid) {
 	    fail("cannot fork: $!");
diff --git a/checks/init.d b/checks/init.d
index 5454286..fb8e33d 100644
--- a/checks/init.d
+++ b/checks/init.d
@@ -21,6 +21,9 @@
 package Lintian::init_d;
 use strict;
 use Util;
+
+use File::Basename qw(dirname);
+use Lintian::Check qw($PKGNAME_REGEX);
 use Lintian::Tags qw(tag);
 
 # A list of valid LSB keywords.	 The value is 0 if optional and 1 if required.
@@ -220,6 +223,11 @@ sub check_init {
 	if ($target =~ m,(?:\A|/)lib/init/upstart-job\z,) {
 	    return;
 	}
+	if (!is_ancestor_of(dirname($initd_file), $initd_file)) {
+	    # unsafe symlink, skip.  NB: dirname($initd_file) is safe
+	    # because coll/init.d does sanity checking for us.
+	    return;
+	}
     }
     open(IN, '<', $initd_file)
 	or fail("cannot open init.d file $initd_file: $!");
diff --git a/checks/menu-format b/checks/menu-format
index bbb4bc8..eaa1a4f 100644
--- a/checks/menu-format
+++ b/checks/menu-format
@@ -428,6 +428,7 @@ foreach my $menufile (@menufiles) {
     $fullname = "/usr/lib/menu/$basename" if $menufile =~ m,^menu/lib/,o;
 
     next if $basename eq "README"; # README is a special case
+    next if !is_ancestor_of('menu', $menufile);
 
     my $menufile_line ="";
     open (IN, '<', $menufile) or
@@ -704,12 +705,19 @@ sub VerifyIcon {
 	$iconfile = "unpacked/usr/share/pixmaps/$icon";
     }
 
-    if (! open (IN, '<', $iconfile)) {
-	tag "menu-icon-missing", "$icon";
-	return;
+    if (-e $iconfile) {
+        if (!is_ancestor_of("unpacked", $iconfile)) {
+            # unsafe symlink
+            return;
+        }
+    } else {
+        tag 'menu-icon-missing', $icon;
+        return;
     }
 
-    my $parse = "XPM header";
+    open (IN, '<', $iconfile) or fail "open $iconfile: $!";
+
+    my $parse = 'XPM header';
     my $line;
     do { defined ($line = <IN>) or goto parse_error; }
     until ($line =~ /\/\*\s*XPM\s*\*\//);
diff --git a/checks/menus b/checks/menus
index 08622ac..b915c8e 100644
--- a/checks/menus
+++ b/checks/menus
@@ -190,7 +190,8 @@ if ($docbase_file) {
     my $dbfile;
     while (defined ($dbfile = readdir DOCBASEDIR)) {
 	# don't try to parse executables, plus we already warned about it
-	next if -x "doc-base/$dbfile";
+	# - skip symlinks as well, unlikely to be used for real doc-base files.
+	next if -x "doc-base/$dbfile" or -l "doc-base/$dbfile";
 	check_doc_base_file($dbfile, $pkg, $type, \%all_files, \%all_links);
     }
     closedir DOCBASEDIR;
diff --git a/checks/patch-systems b/checks/patch-systems
index 9934d46..ae521fe 100644
--- a/checks/patch-systems
+++ b/checks/patch-systems
@@ -47,16 +47,25 @@ sub run {
 	my $quilt_format = ($format =~ /3\.\d+ \(quilt\)/) ? 1 : 0;
 
 	my $cwd = realpath('.');
+	if (!is_ancestor_of("debfiles", "debfiles/patches")) {
+	    # skip, bad symlink
+	    return;
+	}
 
 	#----- dpatch
 	if ($build_deps->implies("dpatch")) {
 		$uses_patch_system++;
 		#check for a debian/patches file:
-		if (! -r "debfiles/patches/00list") {
+		if (-l "debfiles/patches/00list"
+			and not is_ancestor_of("debfiles", "debfiles/patches/00list")) {
+			# skip
+		} elsif (! -r "debfiles/patches/00list") {
 			tag "dpatch-build-dep-but-no-patch-list";
 		} else {
 			my $list_uses_cpp = 0;
-			if (open(OPTS, '<', "debfiles/patches/00options")) {
+			if (-f "debian/patches/00options"
+				   && is_ancestor_of("debfiles", "debfiles/patches/00options")) {
+				open(OPTS, '<', "debfiles/patches/00options") or fail "open 00options: $!";
 				while(<OPTS>) {
 					if (/DPATCH_OPTION_CPP=1/) {
 						$list_uses_cpp = 1;
@@ -67,7 +76,8 @@ sub run {
 			}
 			foreach my $listfile (glob("debfiles/patches/00list*")) {
 				my @patches;
-				if (open(IN, '<', "$listfile")) {
+				if ( -f $listfile && is_ancestor_of("debfiles", $listfile)) {
+					open(IN, '<', "$listfile") or fail "open $listfile: $!";
 					while(<IN>) {
 						chomp;
 						next if (/^\#/); #ignore comments or CPP directive
@@ -119,7 +129,10 @@ sub run {
 	if ($build_deps->implies("quilt") or $quilt_format) {
 		$uses_patch_system++;
 		#check for a debian/patches file:
-		if (! -r "debfiles/patches/series") {
+		if (-l "debfiles/patches/series" and
+		    not is_ancestor_of("debfiles", "debfiles/patches/series")) {
+			# skip
+		} elsif (! -r "debfiles/patches/series") {
 			tag "quilt-build-dep-but-no-series-file" unless $quilt_format;
 		} else {
 			if (open(IN, '<', "debfiles/patches/series")) {
@@ -174,13 +187,18 @@ sub run {
 		if (-r "debfiles/patches/series" and
 		    -f "debfiles/patches/series") {
 			# 3.0 (quilt) sources don't need quilt as dpkg-source will do the work
-			tag "quilt-series-but-no-build-dep" unless $quilt_format;
+			if (! -l "debfiles/patches/series"
+				    or is_ancestor_of("defiles", "debfiles/patches/series")) {
+				tag "quilt-series-but-no-build-dep" unless $quilt_format;
+			}
 		}
 	}
 
 	#----- look for README.source
 	if ($uses_patch_system && ! $quilt_format && ! -f 'debfiles/README.source') {
-		tag "patch-system-but-no-source-readme";
+		if (! -l "debfiles/README.source") {
+			tag "patch-system-but-no-source-readme";
+		}
 	}
 
 	#----- general cruft checking:
diff --git a/checks/po-debconf b/checks/po-debconf
index 902c4ee..8c878d6 100644
--- a/checks/po-debconf
+++ b/checks/po-debconf
@@ -39,6 +39,7 @@ my $has_template = my $has_depends = my $has_config = 0;
 my @lang_templates;
 for my $file (readdir(DEB)) {
 	next if -d "debfiles/$file";
+	next if !is_ancestor_of("debfiles", "debfiles/$file");
 	if ($file =~ m/^(.+\.)?templates(\..+)?$/) {
 		if ($file =~ m/templates\.\w\w(_\w\w)?$/) {
 			push (@lang_templates, $file);
@@ -70,6 +71,10 @@ closedir(DEB);
 
 #TODO: check whether all templates are named in TEMPLATES.pot
 if ( $has_template ) {
+    if ( -l "debfiles/po" and !is_ancestor_of("debfiles", "debfiles/po")) {
+        # debian/po is an unsafe symlink - lets stop here.
+        return;
+    }
     if ( ! -d "debfiles/po" ) {
 	tag "not-using-po-debconf", "";
 	return 0;
@@ -89,7 +94,7 @@ for (@lang_templates) {
 # check).
 my $missing_files = 0;
 my $yada = 0;
-if (open (RULES, '<', 'debfiles/rules')) {
+if ( ! -l "debfiles/rules" and open (RULES, '<', 'debfiles/rules')) {
     local $_;
     while (<RULES>) {
 	if (m%^\t\s*(?:perl debian/)?yada\s%) {
@@ -99,7 +104,7 @@ if (open (RULES, '<', 'debfiles/rules')) {
     }
 }
 
-if (!$yada && -f "debfiles/po/POTFILES.in") {
+if (!$yada && -f "debfiles/po/POTFILES.in" and ! -l "debfiles/po/POTFILES.in") {
 	open(POTFILES, '<', "debfiles/po/POTFILES.in")
 		or fail("Can't open debfiles/po/POTFILES.in.");
 	while (<POTFILES>) {
@@ -118,7 +123,7 @@ if (!$yada && -f "debfiles/po/POTFILES.in") {
 	tag "missing-potfiles-in", "";
 	$missing_files = 1;
 }
-if (! -f "debfiles/po/templates.pot") {
+if (! -f "debfiles/po/templates.pot" and ! -l "debfiles/po/templates.pot") {
 	tag "missing-templates-pot", "";
 	$missing_files = 1;
 }
@@ -146,6 +151,8 @@ while (defined(my $file=readdir(DEBIAN))) {
                 unless ($file =~ /^[a-z]{2,3}(_[A-Z]{2})?\.po$/);
         local ($/) = "\n\n";
         $_ = '';
+        next if -l "debfiles/po/$file" or ! -f "debfiles/po/$file";
+
         open(PO, '<', "debfiles/po/$file")
                 or fail("Can't open debfiles/po/$file file.");
         while (<PO>) {
diff --git a/checks/rules b/checks/rules
index 358db41..91b9209 100644
--- a/checks/rules
+++ b/checks/rules
@@ -110,7 +110,7 @@ my $info = shift;
 # all the tests if we then can't read it.
 if (-l "debfiles/rules") {
     tag "debian-rules-is-symlink", "";
-    return 0 unless -f "debfiles/rules";
+    return 0 unless -f "debfiles/rules" and is_ancestor_of("debfiles", "debfiles/rules");
 }
 
 #get architecture field:
diff --git a/checks/shared-libs b/checks/shared-libs
index dbe78a2..e374239 100644
--- a/checks/shared-libs
+++ b/checks/shared-libs
@@ -279,7 +279,9 @@ for (keys %SONAME) {
 }
 @shlibs = grep { !$unversioned_shlibs{$_} } keys %SONAME;
 
-if ($#shlibs == -1) {
+if (-l 'control/shlibs') {
+    # control files are not symlinks, skip this part.
+} elsif ($#shlibs == -1) {
     # no shared libraries included in package, thus shlibs control file should
     # not be present
     if (-f 'control/shlibs') {
@@ -357,7 +359,9 @@ if ($#shlibs == -1) {
 
 # 5th step: check symbols control file.  Add back in the unversioned shared
 # libraries, since they can still have symbols files.
-if ($#shlibs == -1 and not %unversioned_shlibs) {
+if (-l 'control/symbols') {
+    # control files are not symlinks, skip this part.
+} elsif ($#shlibs == -1 and not %unversioned_shlibs) {
     # no shared libraries included in package, thus symbols control file should
     # not be present
     if (-f 'control/symbols') {
diff --git a/checks/watch-file b/checks/watch-file
index aa11b7a..0e8f453 100644
--- a/checks/watch-file
+++ b/checks/watch-file
@@ -25,6 +25,7 @@ use strict;
 
 use Lintian::Collect;
 use Lintian::Tags qw(tag);
+use Util;
 
 sub run {
 
@@ -32,6 +33,9 @@ my $pkg = shift;
 my $type = shift;
 my $info = shift;
 
+if (-l "debfiles/watch") {
+    return unless is_ancestor_of("debfiles", "debfiles/watch");
+}
 if (! -f "debfiles/watch") {
     tag 'debian-watch-file-is-missing' unless ($info->native);
     return;
diff --git a/debian/changelog b/debian/changelog
index 42eaa23..962f449 100755
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,7 @@
 lintian (2.4.3+squeeze2) stable; urgency=low
 
+  * checks/*:
+    + [NT] Avoid following unsafe symlinks.
   * checks/debconf:
     + [NT] Fix several path traversal issues that could leak
       information about the host system.

-- 
Debian package checker


Reply to: