The following commit has been merged in the squeeze branch:
commit 1344d571ac9fce8f2e80d4ecd88995f5c481e82f
Author: Adam D. Barratt <a...@adam-barratt.org.uk>
Date:   Sun Feb 12 19:37:00 2012 +0000

    Fix CVE-2012-0211 and CVE-2012-0212 (argument injection / modification)
    
    Signed-off-by: Adam D. Barratt <a...@adam-barratt.org.uk>

diff --git a/scripts/debdiff.pl b/scripts/debdiff.pl
index ae32df2..1ba66f5 100755
--- a/scripts/debdiff.pl
+++ b/scripts/debdiff.pl
@@ -17,7 +17,10 @@
 use 5.006_000;
 use strict;
 use Cwd;
+use Dpkg::IPC;
 use File::Basename;
+use File::Copy qw/ cp move /;
+use File::Path qw/ rmtree /;
 use File::Temp qw/ tempdir tempfile /;
 use lib '/usr/share/devscripts';
 use Devscripts::Versort;
@@ -341,10 +344,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
@@ -381,7 +401,7 @@ elsif ($type eq 'changes' or $type eq 'debs') {
                last if $infiles and /^[^ ]/;
                /^Files:/ and $infiles=1, next;
                next unless $infiles;
-               / (\S*.u?deb)$/ and push @debs, dirname($changes) . '/' . $1;
+               / (\S*.u?deb)$/) && push @debs, dirname($changes) . '/' . $1;
            }
            close CHANGES
                or fatal "Problem reading $changes: $!";
@@ -395,10 +415,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/_.*//;
@@ -503,30 +539,27 @@ elsif ($type eq 'dsc') {
        and scalar(@excludes) == 0 and $use_interdiff and 
!$wdiff_source_control) {
        # same orig tar ball, interdiff exists and not wdiffing
 
-       my $command = join( " ", ("interdiff", "-z", @diff_opts, "'$diffs[1]'",
-           "'$diffs[2]'", ">", $filename) );
-       my $rv = system($command);
-       if ($rv) {
-           fatal "interdiff -z $diffs[1] $diffs[2] failed!";
-       } else {
-           if ($have_diffstat and $show_diffstat) {
-               my $header = "diffstat for " . basename($diffs[1])
-                               . " " . basename($diffs[2]) . "\n\n";
-               $header =~ s/\.diff\.gz//g;
-               print $header;
-               system("diffstat $filename");
-               print "\n";
-           }
-
-           if (-s $filename) {
-               open( INTERDIFF, '<', $filename );
-               while( <INTERDIFF> ) {
-                   print $_;
-               }
-               close INTERDIFF;
+       spawn(exec => ['interdiff', '-z', @diff_opts, $diffs[1], $diffs[2]],
+             to_file => $filename,
+             wait_child => 1);
+       if ($have_diffstat and $show_diffstat) {
+           my $header = "diffstat for " . basename($diffs[1])
+                           . " " . basename($diffs[2]) . "\n\n";
+           $header =~ s/\.diff\.gz//g;
+           print $header;
+           spawn(exec => ['diffstat', $filename],
+               wait_child => 1);
+           print "\n";
+       }
 
-               $exit_status = 1;
+       if (-s $filename) {
+           open( INTERDIFF, '<', $filename );
+           while( <INTERDIFF> ) {
+               print $_;
            }
+           close INTERDIFF;
+
+           $exit_status = 1;
        }
     } else {
        # Any other situation
@@ -543,44 +576,67 @@ elsif ($type eq 'dsc') {
            no strict 'refs';
            my @opts = ('-x');
            push (@opts, '--skip-patches') if $dscformats[$i] eq '3.0 (quilt)';
-           my $cmd = qq(cd ${"dir$i"} && dpkg-source @opts $dscs[$i] 
>/dev/null);
-           system $cmd;
-           if ($? != 0) {
-                   my $dir = dirname $dscs[1] if $i == 2;
-                   $dir = dirname $dscs[2] if $i == 1;
-                   my $cmdx = qq(cp $dir/$origs[$i] ${"dir$i"} >/dev/null);
-                   system $cmdx;
-                   fatal "$cmd failed" if $? != 0;
-                   my $dscx = basename $dscs[$i];
-                   $cmdx = qq(cp $diffs[$i] ${"dir$i"} && cp $dscs[$i] 
${"dir$i"} && cd ${"dir$i"} && dpkg-source @opts $dscx > /dev/null);
-                   system $cmdx;
-                   fatal "$cmd failed" if $? != 0;
+           my $diri = ${"dir$i"};
+           eval {
+               spawn(exec => ['dpkg-source', @opts, $dscs[$i]],
+                     to_file => '/dev/null',
+                     chdir => $diri,
+                     wait_child => 1);
+           };
+           if ($@) {
+               my $dir = dirname $dscs[1] if $i == 2;
+               $dir = dirname $dscs[2] if $i == 1;
+               cp "$dir/$origs[$i]", $diri || fatal "copy $dir/$origs[$i] 
$diri: $!";
+               my $dscx = basename $dscs[$i];
+               cp $diffs[$i], $diri || fatal "copy $diffs[$i] $diri: $!";
+               cp $dscs[$i], $diri || fatal "copy $dscs[$i] $diri: $!";
+               spawn(exec => ['dpkg-source', @opts, $dscx],
+                     to_file => '/dev/null',
+                     chdir => $diri,
+                     wait_child => 1);
            }
-           opendir DIR,${"dir$i"};
+           opendir DIR,$diri;
            while ($_ = readdir(DIR)) {
-                   next if $_ eq '.' || $_ eq '..' || ! -d ${"dir$i"}."/$_";
-                   ${"sdir$i"} = $_;
-                   last;
+               next if $_ eq '.' || $_ eq '..' || ! -d "$diri/$_";
+               ${"sdir$i"} = $_;
+               last;
            }
            closedir(DIR);
+           my $sdiri = ${"sdir$i"};
 
            # also unpack tarballs found in the top level source directory so 
we can compare their contents too
            next unless $unpack_tarballs;
-           opendir DIR,${"dir$i"}.'/'.${"sdir$i"};
+           opendir DIR,$diri.'/'.$sdiri;
 
            my $tarballs = 1;
            while ($_ = readdir(DIR)) {
                    my $unpacked = "=unpacked-tar" . $tarballs . "=";
                    my $filename = $_;
+                   my $found = 0;
+                   my $comp = "";
+
                    if ($_ =~ /tar.gz$/) {
                        $filename =~ s%(.*)\.tar\.gz$%$1%;
                        $tarballs++;
-                       system qq(cd ${"dir$i"}/${"sdir$i"} && tar zxf $_ 
>/dev/null && test -d $filename && mv $filename $unpacked); 
+                       $found = 1;
+                       $comp = "gzip";
                    }
                    if ($_ =~ /tar.bz$/ || $_ =~ /tar.bz2$/) {
                        $filename =~ s%(.*)\.tar\.bz2?$%$1%;
                        $tarballs++;
-                       system qq(cd ${"dir$i"}/${"sdir$i"} && tar jxf $_ 
>/dev/null && test -d $filename && mv $filename $unpacked);
+                       $found = 1;
+                       $comp = "bzip2";
+                   }
+
+                   if ($found) {
+                       spawn(exec => ['tar', "--$comp", '-xf', $_],
+                           to_file => '/dev/null',
+                           wait_child => 1,
+                           chdir => "$diri/$sdiri",
+                           nocheck => 1);
+                       if (-d "$diri/$sdiri/$filename") {
+                           move "$diri/$sdiri/$filename", 
"$diri/$sdiri/$unpacked";
+                       }
                    }
            }
            closedir(DIR);
@@ -588,18 +644,18 @@ elsif ($type eq 'dsc') {
 
        my @command = ("diff", "-Nru", @diff_opts);
        for my $exclude (@excludes) {
-           push @command, ("--exclude", "'$exclude'");
+           push @command, ("--exclude", $exclude);
        }
-       push @command, ("'$dir1/$sdir1'", "'$dir2/$sdir2'");
-       push @command, (">", $filename);
+       push @command, ("$dir1/$sdir1", "$dir2/$sdir2");
 
        # Execute diff and remove the common prefixes $dir1/$dir2, so the patch 
can be used with -p1,
        # as if when interdiff would have been used:
-       system(join(" ", @command));
+       spawn(exec => \@command, to_file => $filename, wait_child => 1, nocheck 
=> 1);
 
        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";
        }
 
@@ -622,7 +678,7 @@ elsif ($type eq 'dsc') {
            no strict 'refs';
            for my $i (1,2) {
                foreach my $file (@cf) {
-                   system qq(cp ${"dir$i"}/${"sdir$i"}/debian/$file 
${"wdiffdir$i"});
+                   cp ${"dir$i"}.'/'.${"sdir$i"}."/debian/$file", 
${"wdiffdir$i"};
                }
            }
            use strict 'refs';
@@ -635,7 +691,7 @@ elsif ($type eq 'dsc') {
            print "\n";
 
            # Clean up
-           system ("rm", "-rf", $wdiffdir1, $wdiffdir2);
+           rmtree([$wdiffdir1, $wdiffdir2]);
        }
 
        if (! -f $filename) {
@@ -848,9 +904,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;
        }
     }
@@ -860,7 +922,7 @@ for my $debname (@CommonDebs) {
        $exit_status);
 
     # Clean up
-    system ("rm", "-rf", $dir1, $dir2);
+    rmtree([$dir1, $dir2]);
 }
 
 exit $exit_status;
@@ -959,15 +1021,24 @@ 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";
@@ -977,13 +1048,10 @@ sub wdiff_control_files($$$$$)
                @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 join("\n",@output), "\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 pkg-devscripts-unsubscr...@teams.debian.net.

Reply via email to