The following commit has been merged in the master branch:
commit 9cbe605d3eab4f9e67525f69b676c55b273b7a03
Author: Adam D. Barratt <[email protected]>
Date:   Wed Feb 15 00:02:58 2012 +0000

    debdiff: fix CVE-2012-2012 (and possibly remnants of CVE-2012-2011)
    
    Extend the changes from #571528 to cover more situations where
    user or file input is passed to an external program.  Fixes
    CVE-2012-2012 (and any instance of CVE-2012-2011 not already
    covered by #571528).

diff --git a/debian/changelog b/debian/changelog
index a54684c..25afc0a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -11,8 +11,13 @@ devscripts (2.11.4) UNRELEASED; urgency=low
     (Closes: #601951)
 
   [ Adam D. Barratt ]
-  * debdiff: Fix a regression in the handling of embedded tarballs (a side
-    effect of the changes introduced to resolve #571528).
+  * debdiff:
+    + Fix a regression in the handling of embedded tarballs (a side
+      effect of the changes introduced to resolve #571528).
+    + Extend the changes from #571528 to cover more situations where
+      user or file input is passed to an external program.  Fixes
+      CVE-2012-2012 (and any instance of CVE-2012-2011 not already
+      covered by #571528).
 
   [ Paul Wise ]
   * suspicious-source: Also ignore mercurial and darcs VCS directories
diff --git a/scripts/debdiff.pl b/scripts/debdiff.pl
index fb602f2..b80c945 100755
--- a/scripts/debdiff.pl
+++ b/scripts/debdiff.pl
@@ -21,6 +21,7 @@ use Dpkg::IPC;
 use Dpkg::Compression;
 use File::Copy qw(cp move);
 use File::Basename;
+use File::Path qw/ rmtree /;
 use File::Temp qw/ tempdir tempfile /;
 use lib '/usr/share/devscripts';
 use Devscripts::Versort;
@@ -341,10 +342,27 @@ if ($type eq 'deb') {
     no strict 'refs';
     foreach my $i (1,2) {
        my $deb = shift;
-       my $debc = `env LC_ALL=C dpkg-deb -c $deb`;
-       $? == 0 or fatal "dpkg-deb -c $deb failed!";
-       my $debI = `env LC_ALL=C dpkg-deb -I $deb`;
-       $? == 0 or fatal "dpkg-deb -I $deb failed!";
+       my ($debc, $debI) = ('', '');
+       my %dpkg_env = ( LC_ALL => 'C' );
+       eval {
+           spawn(exec => ['dpkg-deb', '-c', $deb],
+               env => \%dpkg_env,
+               to_string => \$debc,
+               wait_child => 1);
+       };
+       if ($@) {
+           fatal "dpkg-deb -c $deb failed!";
+       }
+
+       eval {
+           spawn(exec => ['dpkg-deb', '-I', $deb],
+               env => \%dpkg_env,
+               to_string => \$debI,
+               wait_child => 1);
+       };
+       if ($@) {
+           fatal "dpkg-deb -I $deb failed!";
+       }
        # Store the name for later
        $singledeb[$i] = $deb;
        # get package name itself
@@ -400,10 +418,26 @@ elsif ($type eq 'changes' or $type eq 'debs') {
        foreach my $deb (@debs) {
            no strict 'refs';
            fatal "Can't read file: $deb" unless -r $deb;
-           my $debc = `env LC_ALL=C dpkg-deb -c $deb`;
-           $? == 0 or fatal "dpkg-deb -c $deb failed!";
-           my $debI = `env LC_ALL=C dpkg-deb -I $deb`;
-           $? == 0 or fatal "dpkg-deb -I $deb failed!";
+           my ($debc, $debI) = ('', '');
+           my %dpkg_env = ( LC_ALL => 'C' );
+           eval {
+               spawn(exec => ['dpkg-deb', '-c', $deb],
+                   to_string => \$debc,
+                   env => \%dpkg_env,
+                   wait_child => 1);
+           };
+           if ($@) {
+               fatal "dpkg-deb -c $deb failed!";
+           }
+           eval {
+               spawn(exec => ['dpkg-deb', '-I', $deb],
+                   to_string => \$debI,
+                   env => \%dpkg_env,
+                   wait_child => 1);
+           };
+           if ($@) {
+               fatal "dpkg-deb -I $deb failed!";
+           }
            my $debpath = $deb;
            # get package name itself
            $deb =~ s,.*/,,; $deb =~ s/_.*//;
@@ -518,7 +552,8 @@ elsif ($type eq 'dsc') {
                            . " " . basename($diffs[2]) . "\n\n";
            $header =~ s/\.diff\.gz//g;
            print $header;
-           system('diffstat', $filename);
+           spawn(exec => ['diffstat', $filename],
+               wait_child => 1);
            print "\n";
        }
 
@@ -610,7 +645,8 @@ elsif ($type eq 'dsc') {
 
        if ($have_diffstat and $show_diffstat) {
            print "diffstat for $sdir1 $sdir2\n\n";
-           system("diffstat $filename");
+           spawn(exec => ['diffstat', $filename],
+               wait_child => 1);
            print "\n";
        }
 
@@ -646,7 +682,7 @@ elsif ($type eq 'dsc') {
            print "\n";
 
            # Clean up
-           system ("rm", "-rf", $wdiffdir1, $wdiffdir2);
+           rmtree([$wdiffdir1, $wdiffdir2]);
        }
 
        if (! -f $filename) {
@@ -859,9 +895,15 @@ for my $debname (@CommonDebs) {
     mktmpdirs();
 
     for my $i (1,2) {
-       if (system('dpkg-deb', '-e', "${\"DebPaths$i\"}{$debname}", 
${"dir$i"})) {
+       my $debpath = "${\"DebPaths$i\"}{$debname}";
+       my $diri = ${"dir$i"};
+       eval {
+           spawn(exec => ['dpkg-deb', '-e', $debpath, $diri],
+               wait_child => 1);
+       };
+       if ($@) {
            my $msg = "dpkg-deb -e ${\"DebPaths$i\"}{$debname} failed!";
-           system ("rm", "-rf", $dir1, $dir2);
+           rmtree([$dir1, $dir2]);
            fatal $msg;
        }
     }
@@ -871,7 +913,7 @@ for my $debname (@CommonDebs) {
        $exit_status);
 
     # Clean up
-    system ("rm", "-rf", $dir1, $dir2);
+    rmtree([$dir1, $dir2]);
 }
 
 exit $exit_status;
@@ -970,31 +1012,37 @@ sub wdiff_control_files($$$$$)
                close $fd;
            }
        }
-       my $wdiff = `wdiff -n $wdiff_opt $dir1/$cf $dir2/$cf`;
        my $usepkgname = $debname eq $dummyname ? "" : " of package $debname";
-       if ($? >> 8 == 0) {
-           if (! $quiet) {
-               print "\nNo differences were encountered between the $cf 
files$usepkgname\n";
-           }
-       } elsif ($? >> 8 == 1) {
-           print "\n";
-           if ($wdiff_opt) {
+       my @opts = ('-n');
+       push @opts, $wdiff_opt if $wdiff_opt;
+       my $wdiff = '';
+       eval {
+           spawn(exec => ['wdiff', @opts, "$dir1/$cf", "$dir2/$cf"],
+               to_string => \$wdiff,
+               wait_child => 1);
+       };
+       if ($@ and $@ !~ /gave error exit status 1/) {
+           print "$@\n";
+           warn "wdiff failed\n";
+       } else {
+           if (!$@) {
+               if (! $quiet) {
+                   print "\nNo differences were encountered between the $cf 
files$usepkgname\n";
+               }
+           } elsif ($wdiff_opt) {
                # Don't try messing with control codes
                my $msg = ucfirst($cf) . " files$usepkgname: wdiff output";
-               print $msg, "\n", '-' x length $msg, "\n";
+               print "\n", $msg, "\n", '-' x length $msg, "\n";
                print $wdiff;
            } else {
                my @output;
                @output = split /\n/, $wdiff;
                @output = grep /(\[-|\{\+)/, @output;
                my $msg = ucfirst($cf) . " files$usepkgname: lines which differ 
(wdiff format)";
-               print $msg, "\n", '-' x length $msg, "\n";
+               print "\n", $msg, "\n", '-' x length $msg, "\n";
                print join("\n",@output), "\n";
            }
            $status = 1;
-       } else {
-           warn "wdiff failed (exit status " . ($? >> 8) .
-               (($? & 0x7f) ? " with signal " . ($? & 0x7f) : "") . ")\n";
        }
     }
 

-- 
Git repository for devscripts


-- 
To unsubscribe, send mail to [email protected].

Reply via email to