diff options
author | Jean Delvare <jdelvare@suse.de> | 2019-03-14 16:42:37 +0100 |
---|---|---|
committer | Jean Delvare <jdelvare@suse.de> | 2019-03-14 16:42:37 +0100 |
commit | cb1c50af1792ea482857d82dec825e4312657410 (patch) | |
tree | 1ba73f48482f8925acad7ed19b472595a640254e /test | |
parent | 991d4e55ad6409b4b3fb893dfbab3907601ba594 (diff) | |
download | quilt-cb1c50af1792ea482857d82dec825e4312657410.tar.gz |
test: Prevent test cases from escaping
By default, we continue running tests even after a failure, to make
diagnostics easier. If a chdir command fails, there is a chance that
subsequent chdir commands could accidentally move outside the
temporary directory where the test is being run, and then we start
messing up with the host's files.
In general, the consequence is to leave garbage files and directories
behind. However, some of the files can have side effects (for example
a "series" file or a "patches" directory could confuse quilt later),
and in theory this could also lead to the corruption or deletion of
existing files, which is pretty bad.
So add a safety check after every chdir command that we are still
inside the test case's working directory. If not, stop the test
immediately.
Note: this is not about being 100% safe and bullet-proof. The only
way to achieve this would be to use chroot or even containers. We
still need to trust the test cases to not do anything nasty on
purpose. This is only protecting against good test cases going wild on
failure.
Signed-off-by: Jean Delvare <jdelvare@suse.de>
Diffstat (limited to 'test')
-rwxr-xr-x | test/run | 21 |
1 files changed, 17 insertions, 4 deletions
@@ -70,6 +70,7 @@ my $lineno; my $width = ($ENV{COLUMNS} || 80) >> 1; my $origdir = getcwd; my $workdir = defined $ARGV[0] ? "$ARGV[0].$$" : "d.$$"; +my $workdir_absolute; my $keep_workdir = $ENV{KEEP_WORKDIR_IF_FAILED} || 0; sub print_header($) @@ -116,6 +117,11 @@ sub substitute_vars($) return $line; } +sub begins_with($$) +{ + return substr($_[0], 0, length($_[1])) eq $_[1]; +} + sub exec_test($$) { my ($raw_prog, $in) = @_; local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2); @@ -130,6 +136,11 @@ sub exec_test($$) { return 1, [ "chdir: $prog->[1]: $!\n" ]; } $ENV{PWD} = getcwd; + # We must always stay inside the test directory + unless (begins_with("$ENV{PWD}/", "$workdir_absolute/")) { + return 1, [ "Illegal chdir $prog->[1]\n", + "$ENV{PWD} is not inside $workdir_absolute" ], 1; + } return 0, []; } elsif ($prog->[0] eq "export") { my ($name, $value) = split /=/, $prog->[1]; @@ -220,7 +231,7 @@ sub process_test($$$$) { my ($prog, $prog_line, $in, $out) = @_; print_body "[$prog_line] \$ $prog -- "; - my ($exec_status, $result) = exec_test($prog, $in); + my ($exec_status, $result, $stop) = exec_test($prog, $in); my @good = (); my $good = 1; my $nmax = (@$out > @$result) ? @$out : @$result; @@ -250,7 +261,7 @@ sub process_test($$$$) { } } - return $exec_status; + return $exec_status, $stop; } # Create a dedicated working directory @@ -259,6 +270,7 @@ mkdir $workdir or die "Failed to create directory $workdir: $!"; $SIG{INT} = sub { if (chdir $origdir) { system "rm -rf $workdir" }; exit 1; }; chdir $workdir or die "Failed to change to directory $workdir: $!"; $ENV{PWD} = getcwd; +$workdir_absolute = $ENV{PWD}; if (defined $ARGV[0]) { open(SOURCE, "$origdir/$ARGV[0]"); @@ -282,9 +294,10 @@ while (defined(my $line = <SOURCE>)) { # We have all input and output, we can execute the command if (defined $prog) { - $last_status = process_test($prog, $prog_line, $in, $out); + my $stop; + ($last_status, $stop) = process_test($prog, $prog_line, $in, $out); $prog = undef; - last if $prog_line >= $opt_l; + last if $prog_line >= $opt_l || $stop; } # Parse the next command |