diff options
-rw-r--r-- | debian/changelog | 22 | ||||
-rw-r--r-- | dpkg-split/split.c | 2 | ||||
-rw-r--r-- | man/po/fr.po | 4 | ||||
-rw-r--r-- | scripts/Dpkg/Source/Archive.pm | 2 | ||||
-rw-r--r-- | scripts/Dpkg/Source/Package/V2.pm | 7 | ||||
-rw-r--r-- | scripts/Dpkg/Source/Patch.pm | 98 |
6 files changed, 95 insertions, 40 deletions
diff --git a/debian/changelog b/debian/changelog index ceaae4a7a..5766ac781 100644 --- a/debian/changelog +++ b/debian/changelog @@ -48,6 +48,28 @@ dpkg (1.16.0) UNRELEASED; urgency=low -- Guillem Jover <guillem@debian.org> Thu, 29 Jul 2010 11:00:22 +0200 +dpkg (1.15.8.8) unstable; urgency=low + + [ Guillem Jover ] + * Truncate the output part file on “dpkg-split -s”. Regression introduced + with the C rewrite. + + [ Updated man page translations ] + * Two typos fixed in French (Christian Perrier, thanks to Julien + Valroff). + + [ Raphaël Hertzog ] + * Fix multiple security issues with dpkg-source (CVE-2010-1679): + - Enhance checks to catch maliciously crafted patches which could modify + files outside of the unpacked source package. + - Do not consider a top-level symlink like a directory when + extracting a tarball. + - Exclude .pc while extracting the upstream tarball in 3.0 (quilt) + as patch blindly writes in that directory during unpack (and would + follow any existing symlink). + + -- Raphaël Hertzog <hertzog@debian.org> Thu, 06 Jan 2011 21:04:33 +0100 + dpkg (1.15.8.7) unstable; urgency=low [ Guillem Jover ] diff --git a/dpkg-split/split.c b/dpkg-split/split.c index 4d54cf20f..6992cad47 100644 --- a/dpkg-split/split.c +++ b/dpkg-split/split.c @@ -197,7 +197,7 @@ mksplit(const char *file_src, const char *prefix, size_t partsize, } /* Split the data. */ - fd_dst = open(file_dst.buf, O_CREAT | O_WRONLY, 0644); + fd_dst = creat(file_dst.buf, 0644); if (fd_dst < 0) ohshite(_("unable to open file '%s'"), file_dst.buf); diff --git a/man/po/fr.po b/man/po/fr.po index f8ec468e4..3fea7b1a0 100644 --- a/man/po/fr.po +++ b/man/po/fr.po @@ -5612,7 +5612,7 @@ msgid "" "build of Debian packages." msgstr "" "B<dpkg-buildflags> est un script qui permet de récupérer les options de " -"compilation à utiliser pour laconstruction d'un paquet." +"compilation à utiliser pour la construction d'un paquet." #. type: Plain text #: dpkg-buildflags.1:15 @@ -5646,7 +5646,7 @@ msgid "" "for the current user with B<$XDG_CONFIG_HOME/dpkg/buildflags.conf> where B<" "$XDG_CONFIG_HOME> defaults to B<$HOME/.config>;" msgstr "" -"pouyr l'utilisateur courant avec B<$XDG_CONFIG_HOME/dpkg/buildflags.conf> où " +"pour l'utilisateur courant avec B<$XDG_CONFIG_HOME/dpkg/buildflags.conf> où " "la valeur par défaut de B<$XDG_CONFIG_HOME> est B<$HOME/.config>;" #. type: IP diff --git a/scripts/Dpkg/Source/Archive.pm b/scripts/Dpkg/Source/Archive.pm index 921c76e6f..5e040cad4 100644 --- a/scripts/Dpkg/Source/Archive.pm +++ b/scripts/Dpkg/Source/Archive.pm @@ -147,7 +147,7 @@ sub extract { closedir(D); my $done = 0; erasedir($dest); - if (scalar(@entries) == 1 && -d "$tmp/$entries[0]") { + if (scalar(@entries) == 1 && ! -l "$tmp/$entries[0]" && -d _) { rename("$tmp/$entries[0]", $dest) || syserr(_g("Unable to rename %s to %s"), "$tmp/$entries[0]", $dest); diff --git a/scripts/Dpkg/Source/Package/V2.pm b/scripts/Dpkg/Source/Package/V2.pm index 8f6618eeb..4eaad9376 100644 --- a/scripts/Dpkg/Source/Package/V2.pm +++ b/scripts/Dpkg/Source/Package/V2.pm @@ -133,7 +133,12 @@ sub do_extract { # Extract main tarball info(_g("unpacking %s"), $tarfile); my $tar = Dpkg::Source::Archive->new(filename => "$dscdir$tarfile"); - $tar->extract($newdirectory, no_fixperms => 1); + $tar->extract($newdirectory, no_fixperms => 1, + options => [ "--anchored", "--no-wildcards-match-slash", + "--exclude", "*/.pc", "--exclude", ".pc" ]); + # The .pc exclusion is only needed for 3.0 (quilt) and to avoid + # having an upstream tarball provide a directory with symlinks + # that would be blindly followed when applying the patches # Extract additional orig tarballs foreach my $subdir (keys %origtar) { diff --git a/scripts/Dpkg/Source/Patch.pm b/scripts/Dpkg/Source/Patch.pm index efeef5d6b..59d1004a3 100644 --- a/scripts/Dpkg/Source/Patch.pm +++ b/scripts/Dpkg/Source/Patch.pm @@ -307,11 +307,41 @@ sub analyze { $header =~ s/\s.*// unless ($header =~ s/\t.*//); return $header; } + sub intuit_file_patched { + my ($old, $new) = @_; + return $new unless defined $old; + return $old unless defined $new; + return $new if -e $new and not -e $old; + return $old if -e $old and not -e $new; + # We don't consider the case where both files are non-existent and + # where patch picks the one with the fewest directories to create + # since dpkg-source will pre-create the required directories + # + # Precalculate metrics used by patch + my ($tmp_o, $tmp_n) = ($old, $new); + my ($len_o, $len_n) = (length($old), length($new)); + $tmp_o =~ s{[/\\]+}{/}g; + $tmp_n =~ s{[/\\]+}{/}g; + my $nb_comp_o = ($tmp_o =~ tr{/}{/}); + my $nb_comp_n = ($tmp_n =~ tr{/}{/}); + $tmp_o =~ s{^.*/}{}; + $tmp_n =~ s{^.*/}{}; + my ($blen_o, $blen_n) = (length($tmp_o), length($tmp_n)); + # Decide like patch would + if ($nb_comp_o != $nb_comp_n) { + return ($nb_comp_o < $nb_comp_n) ? $old : $new; + } elsif ($blen_o != $blen_n) { + return ($blen_o < $blen_n) ? $old : $new; + } elsif ($len_o != $len_n) { + return ($len_o < $len_n) ? $old : $new; + } + return $old; + } $_ = getline($self); HUNK: while (defined($_) || not eof($self)) { - my ($fn, $fn2); + my (%path, %fn); # skip comments leading up to patch (if any) until (/^--- /) { last HUNK if not defined($_ = getline($self)); @@ -321,11 +351,8 @@ sub analyze { unless(s/^--- //) { error(_g("expected ^--- in line %d of diff `%s'"), $., $diff); } - $_ = strip_ts($_); - if ($_ eq '/dev/null' or s{^[^/]+/}{$destdir/}) { - $fn = $_; - error(_g("%s contains an insecure path: %s"), $diff, $_) if m{/\.\./}; - } + $path{'old'} = $_ = strip_ts($_); + $fn{'old'} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/}; if (/\.dpkg-orig$/) { error(_g("diff `%s' patches file with name ending .dpkg-orig"), $diff); } @@ -336,46 +363,47 @@ sub analyze { unless (s/^\+\+\+ //) { error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.); } - $_ = strip_ts($_); - if ($_ eq '/dev/null' or s{^[^/]+/}{$destdir/}) { - $fn2 = $_; - error(_g("%s contains an insecure path: %s"), $diff, $_) if m{/\.\./}; - } else { - unless (defined $fn) { - error(_g("none of the filenames in ---/+++ are relative in diff `%s' (line %d)"), - $diff, $.); - } - } + $path{'new'} = $_ = strip_ts($_); + $fn{'new'} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/}; + + unless (defined $fn{'old'} or defined $fn{'new'}) { + error(_g("none of the filenames in ---/+++ are valid in diff '%s' (line %d)"), + $diff, $.); + } - if (defined($fn) and $fn eq '/dev/null') { + # Safety checks on both filenames that patch could use + foreach my $key ("old", "new") { + next unless defined $fn{$key}; + if ($path{$key} =~ m{/\.\./}) { + error(_g("%s contains an insecure path: %s"), $diff, $path{$key}); + } + my $path = $fn{$key}; + while (1) { + if (-l $path) { + error(_g("diff %s modifies file %s through a symlink: %s"), + $diff, $fn{$key}, $path); + } + last unless $path =~ s{/+[^/]*$}{}; + last if length($path) <= length($destdir); # $destdir is assumed safe + } + } + + if ($path{'old'} eq '/dev/null' and $path{'new'} eq '/dev/null') { error(_g("original and modified files are /dev/null in diff `%s' (line %d)"), - $diff, $.) if (defined($fn2) and $fn2 eq '/dev/null'); - $fn = $fn2; - } elsif (defined($fn2) and $fn2 ne '/dev/null') { - $fn = $fn2 unless defined $fn; - $fn = $fn2 if ((not -e $fn) and -e $fn2); - } elsif (defined($fn2) and $fn2 eq '/dev/null') { + $diff, $.); + } elsif ($path{'new'} eq '/dev/null') { error(_g("file removal without proper filename in diff `%s' (line %d)"), - $diff, $. - 1) unless defined $fn; + $diff, $. - 1) unless defined $fn{'old'}; warning(_g("diff %s removes a non-existing file %s (line %d)"), - $diff, $fn, $.) unless -e $fn; + $diff, $fn{'old'}, $.) unless -e $fn{'old'}; } + my $fn = intuit_file_patched($fn{'old'}, $fn{'new'}); my $dirname = $fn; if ($dirname =~ s{/[^/]+$}{} && not -d $dirname) { $dirtocreate{$dirname} = 1; } - # Sanity check, refuse to patch through a symlink - $dirname = $fn; - while (1) { - if (-l $dirname) { - error(_g("diff %s modifies file %s through a symlink: %s"), - $diff, $fn, $dirname); - } - last unless $dirname =~ s{/[^/]+$}{}; - } - if (-e $fn and not -f _) { error(_g("diff `%s' patches something which is not a plain file"), $diff); } |