summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog22
-rw-r--r--dpkg-split/split.c2
-rw-r--r--man/po/fr.po4
-rw-r--r--scripts/Dpkg/Source/Archive.pm2
-rw-r--r--scripts/Dpkg/Source/Package/V2.pm7
-rw-r--r--scripts/Dpkg/Source/Patch.pm98
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);
}