commit 678079171cdf9cb8f6c2cfe937949f08d644ef81
Author: Gisle Aas <gisle@aas.no>
Date: Sat Jul 26 11:05:52 2008 +0200
rmtree symlink attack CVE-2004-0452
diff --git a/MANIFEST b/MANIFEST
index f58018c..1366f97 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -7,6 +7,7 @@ Path.pm
README
TODO
eg/setup-extra-tests
+t/CVE-2008-2827.t
t/Path.t
t/pod.t
t/taint.t
diff --git a/Path.pm b/Path.pm
index 5508b4e..f2c99ea 100644
--- a/Path.pm
+++ b/Path.pm
@@ -359,9 +359,9 @@ sub _rmtree {
next ROOT_DIR;
}
- my $nperm = $perm & 07777 | 0600;
- if ($nperm != $perm and not chmod $nperm, $root) {
- if ($Force_Writeable) {
+ if ($Force_Writeable) {
+ my $nperm = $perm & 07777 | 0600;
+ if ($nperm != $perm and not chmod $nperm, $root) {
_error($arg, "cannot make file writeable", $canon);
}
}
diff --git a/t/CVE-2008-2827.t b/t/CVE-2008-2827.t
new file mode 100644
index 0000000..19fa451
--- /dev/null
+++ b/t/CVE-2008-2827.t
@@ -0,0 +1,39 @@
+#!perl -w
+
+# Test case derived from
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=487319
+
+my $foo = "foo-$$";
+my $bar = "bar-$$";
+
+die "Not clean [$foo] [$bar]" if -e $foo || -e $bar;
+
+eval {
+ symlink($foo, $bar) || die "Can't symlink $foo --> $bar";
+};
+if ($@) {
+ print "1..0 # Skipped: Only systems that can do symlinks are affected\n";
+ print "$@\n";
+ exit;
+}
+
+use Test;
+plan tests => 5;
+
+umask(0027);
+
+# touch foo
+open(my $fh, ">", $foo) || die "Can't create $foo\n";
+close($fh);
+
+my $m = (stat $foo)[2];
+ok(defined $m);
+
+require File::Path;
+ok(File::Path::rmtree($bar));
+ok(!-e $bar);
+
+# If the mode of $foo changed as a result of removing $bar then we are vulnerable
+ok($m, (stat $foo)[2]);
+
+unlink($foo);
+ok(!-e $foo);