Added checks to detect directory/symlink switching attacks.
This commit is contained in:
parent
321ed609ff
commit
50a51a6093
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
use strict;
|
use strict;
|
||||||
use File::stat;
|
use File::stat;
|
||||||
|
use POSIX;
|
||||||
|
|
||||||
my $verbose = 0;
|
my $verbose = 0;
|
||||||
my $nop = 0;
|
my $nop = 0;
|
||||||
|
@ -17,10 +18,11 @@ sub cleandir {
|
||||||
if ($verbose > 1) {
|
if ($verbose > 1) {
|
||||||
print STDERR "$0:", " " x $level, " cleandir $dir $since {\n";
|
print STDERR "$0:", " " x $level, " cleandir $dir $since {\n";
|
||||||
}
|
}
|
||||||
if (!opendir(DIR, $dir)) {
|
if (!opendir(DIR, ".")) {
|
||||||
printf STDERR "$0:", " " x $level, " cannot opendir $dir: $!";
|
printf STDERR "$0:", " " x $level, " cannot opendir $dir: $!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
my $std = lstat(".");
|
||||||
for my $i (readdir(DIR)) {
|
for my $i (readdir(DIR)) {
|
||||||
if ($i eq "." || $i eq "..") {next}
|
if ($i eq "." || $i eq "..") {next}
|
||||||
if ($verbose > 2) {
|
if ($verbose > 2) {
|
||||||
|
@ -31,10 +33,35 @@ sub cleandir {
|
||||||
print STDERR "$0:", " " x $level, " mtime=", $st->mtime, " atime=", $st->atime, "\n";
|
print STDERR "$0:", " " x $level, " mtime=", $st->mtime, " atime=", $st->atime, "\n";
|
||||||
}
|
}
|
||||||
if (-d _) {
|
if (-d _) {
|
||||||
|
my $cwd = getcwd();
|
||||||
if (cleandir("$dir/$i", $since, $level+1) == 0 && $st->mtime < $since) {
|
if (!chdir($i)) {
|
||||||
if (rmdir("$dir/$i")) {next}
|
my $st1 = lstat(".");
|
||||||
|
if ($st->dev == $st1->dev && $st->ino == $st1->ino) {
|
||||||
|
if (cleandir("$dir/$i", $since, $level+1) == 0 && $st->mtime < $since) {
|
||||||
|
if (rmdir("$dir/$i")) {next}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print STDERR "$0:", " " x $level,
|
||||||
|
" $dir/$i changed dev/inode from ",
|
||||||
|
$st->dev, "/", $st->ino,
|
||||||
|
" to ",
|
||||||
|
$st1->dev, "/", $st1->ino,
|
||||||
|
"\n";
|
||||||
|
}
|
||||||
|
chdir($cwd);
|
||||||
|
my $std1 = lstat(".");
|
||||||
|
if (!($std->dev == $std1->dev && $std->ino == $std1->ino)) {
|
||||||
|
print STDERR "$0:", " " x $level,
|
||||||
|
" $cwd changed dev/inode from ",
|
||||||
|
$std->dev, "/", $std->ino,
|
||||||
|
" to ",
|
||||||
|
$std1->dev, "/", $std1->ino,
|
||||||
|
"\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print STDERR "$0:", " " x $level, " chdir $dir/$i failed: $!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
} elsif ($st->mtime < $since && $st->atime < $since) {
|
} elsif ($st->mtime < $since && $st->atime < $since) {
|
||||||
if ($nop) {
|
if ($nop) {
|
||||||
print "would remove $dir/$i\n";
|
print "would remove $dir/$i\n";
|
||||||
|
@ -43,7 +70,7 @@ sub cleandir {
|
||||||
print STDERR "$0:", " " x $level, " removing $dir/$i\n";
|
print STDERR "$0:", " " x $level, " removing $dir/$i\n";
|
||||||
}
|
}
|
||||||
if (unlink("$dir/$i")) {next}
|
if (unlink("$dir/$i")) {next}
|
||||||
print STDERR "$0:", " " x $level, " removing $dir/$i failed: $!/$i\n";
|
print STDERR "$0:", " " x $level, " removing $dir/$i failed: $!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,7 +94,11 @@ sub main {
|
||||||
} elsif ($i eq "-n") {
|
} elsif ($i eq "-n") {
|
||||||
$nop++;
|
$nop++;
|
||||||
} else {
|
} else {
|
||||||
cleandir($i, $since, 0);
|
my $cwd = getcwd();
|
||||||
|
if (chdir($i)) {
|
||||||
|
cleandir($i, $since, 0);
|
||||||
|
chdir($cwd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
Loading…
Reference in New Issue