This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch master in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=5490025f9acec8228026a5330f4a740f94f435cf commit 5490025f9acec8228026a5330f4a740f94f435cf Author: Guillem Jover <[email protected]> AuthorDate: Sun Jul 5 16:39:46 2020 +0200 Dpkg::Path: Refactor check_directory_traversal() out of Dpkg::Source::Package This might be useful in other contexts, it is going to get a bit more complex and it will make it possible to unit test it. --- debian/changelog | 2 ++ scripts/Dpkg/Path.pm | 37 ++++++++++++++++++++++++++++++++++++- scripts/Dpkg/Source/Package.pm | 18 ++---------------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/debian/changelog b/debian/changelog index 94543441c..76d6d8dee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,8 @@ dpkg (1.20.4) UNRELEASED; urgency=medium - Dpkg::OpenPGP: Use a temporary directory for the GnuPG homedir in verify_signature(), to make sure we do not write to the user home directory, except for the trustkeys.db file if present. + - Dpkg::Path: Refactor new check_directory_traversal() function out of + Dpkg::Source::Package->extract(). * Build system: - Add Module::Signature as configure recommends for CPAN. * Test suite: diff --git a/scripts/Dpkg/Path.pm b/scripts/Dpkg/Path.pm index f352cac35..ce55b5a54 100644 --- a/scripts/Dpkg/Path.pm +++ b/scripts/Dpkg/Path.pm @@ -19,11 +19,12 @@ package Dpkg::Path; use strict; use warnings; -our $VERSION = '1.04'; +our $VERSION = '1.05'; our @EXPORT_OK = qw( canonpath resolve_symlink check_files_are_the_same + check_directory_traversal find_command find_build_file get_control_path @@ -34,8 +35,11 @@ our @EXPORT_OK = qw( use Exporter qw(import); use File::Spec; +use File::Find; use Cwd qw(realpath); +use Dpkg::ErrorHandling; +use Dpkg::Gettext; use Dpkg::Arch qw(get_host_arch debarch_to_debtuple); use Dpkg::IPC; @@ -202,6 +206,33 @@ sub resolve_symlink($) { } } +=item check_directory_traversal($basedir, $dir) + +This function verifies that the directory $dir does not contain any symlink +that goes beyond $basedir (which should be either equal or a parent of $dir). + +=cut + +sub check_directory_traversal { + my ($basedir, $dir) = @_; + + my $canon_basedir = realpath($basedir); + my $check_symlinks = sub { + my $canon_pathname = realpath($_); + return if $canon_pathname =~ m/^\Q$canon_basedir\E/; + + error(g_("pathname '%s' points outside source root"), $_); + }; + + find({ + wanted => $check_symlinks, + no_chdir => 1, + follow => 1, + follow_skip => 2, + }, $dir); + + return; +} =item $cmdpath = find_command($command) @@ -281,6 +312,10 @@ sub find_build_file($) { =head1 CHANGES +=head2 Version 1.05 (dpkg 1.20.4) + +New function: check_directory_traversal(). + =head2 Version 1.04 (dpkg 1.17.11) Update semantics: find_command() now handles an empty or undef argument. diff --git a/scripts/Dpkg/Source/Package.pm b/scripts/Dpkg/Source/Package.pm index 9698b7527..1b52b0ee3 100644 --- a/scripts/Dpkg/Source/Package.pm +++ b/scripts/Dpkg/Source/Package.pm @@ -44,9 +44,7 @@ our @EXPORT_OK = qw( use Exporter qw(import); use POSIX qw(:errno_h :sys_wait_h); use Carp; -use Cwd qw(realpath); use File::Temp; -use File::Find; use File::Copy qw(cp); use File::Basename; @@ -56,7 +54,7 @@ use Dpkg::Control; use Dpkg::Checksums; use Dpkg::Version; use Dpkg::Compression; -use Dpkg::Path qw(check_files_are_the_same); +use Dpkg::Path qw(check_files_are_the_same check_directory_traversal); use Dpkg::Vendor qw(run_vendor_hook); use Dpkg::Source::Format; use Dpkg::OpenPGP; @@ -556,21 +554,9 @@ sub extract { # Check for directory traversals. if (not $self->{options}{skip_debianization}) { - my $canon_newdir = realpath($newdirectory); - my $check_symlinks = sub { - my $canon_pathname = realpath($_); - return if $canon_pathname =~ m/^\Q$canon_newdir\E/; - - error(g_("pathname '%s' points outside source root"), $_); - }; # We need to add a trailing slash to handle the debian directory # possibly being a symlink. - find({ - wanted => $check_symlinks, - no_chdir => 1, - follow => 1, - follow_skip => 2, - }, "$newdirectory/debian/"); + check_directory_traversal($newdirectory, "$newdirectory/debian/"); } # Store format if non-standard so that next build keeps the same format -- Dpkg.Org's dpkg

