summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <jdelvare@suse.de>2019-03-14 16:42:37 +0100
committerJean Delvare <jdelvare@suse.de>2019-03-14 16:42:37 +0100
commitcb1c50af1792ea482857d82dec825e4312657410 (patch)
tree1ba73f48482f8925acad7ed19b472595a640254e
parent991d4e55ad6409b4b3fb893dfbab3907601ba594 (diff)
downloadquilt-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>
-rwxr-xr-xtest/run21
1 files changed, 17 insertions, 4 deletions
diff --git a/test/run b/test/run
index 85df0ef..0c0ec16 100755
--- a/test/run
+++ b/test/run
@@ -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