diff --git a/debian/changelog b/debian/changelog index 2d401b1..a6c4bc8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,14 @@ dpkg (1.14.29) UNRELEASED; urgency=low - * + * Modify dpkg-source to error out when it would apply patches containing + insecure paths (with "/../") and also error out when it would apply a + patch through a symlink. Those checks are required as patch will happily + modify files outside of the target directory and unpacking a source package + should not be able to have any side-effect outside of the target + directory. + * Also error out when the quilt series contains a path with "/../" as this + can cause patch to create files outside of the source package due + to the -B .pc/$path option that it gets. -- Raphael Hertzog Fri, 05 Mar 2010 20:41:39 +0100 diff --git a/scripts/Dpkg/Source/Package/V3/quilt.pm b/scripts/Dpkg/Source/Package/V3/quilt.pm index 56acc71..15343e0 100644 --- a/scripts/Dpkg/Source/Package/V3/quilt.pm +++ b/scripts/Dpkg/Source/Package/V3/quilt.pm @@ -111,6 +111,7 @@ sub read_patch_list { } } next if $opts{"skip_auto"} and $_ eq $auto_patch; + error(_g("%s contains an insecure path: %s"), $file, $_) if m{(^|/)\.\./}; push @patches, $_; } close(SERIES); diff --git a/scripts/Dpkg/Source/Patch.pm b/scripts/Dpkg/Source/Patch.pm index a205f28..079440a 100644 --- a/scripts/Dpkg/Source/Patch.pm +++ b/scripts/Dpkg/Source/Patch.pm @@ -316,8 +316,9 @@ sub analyze { error(_g("expected ^--- in line %d of diff `%s'"), $., $diff); } $_ = strip_ts($_); - if ($_ eq '/dev/null' or s{^(\./)?[^/]+/}{$destdir/}) { + if ($_ eq '/dev/null' or s{^[^/]+/}{$destdir/}) { $fn = $_; + error(_g("%s contains an insecure path: %s"), $diff, $_) if m{/\.\./}; } if (/\.dpkg-orig$/) { error(_g("diff `%s' patches file with name ending .dpkg-orig"), $diff); @@ -330,8 +331,9 @@ sub analyze { error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.); } $_ = strip_ts($_); - if ($_ eq '/dev/null' or s{^(\./)?[^/]+/}{$destdir/}) { + 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)"), @@ -357,6 +359,17 @@ sub analyze { 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); }