harden file_set_contents against symlink attacks

This commit is contained in:
Wolfgang Bumiller 2016-08-16 16:31:10 +02:00 committed by Fabian Grünbichler
parent c9cb574660
commit aa757172c6

View File

@ -2,7 +2,7 @@ package PVE::Tools;
use strict; use strict;
use warnings; use warnings;
use POSIX qw(EINTR); use POSIX qw(EINTR EEXIST);
use IO::Socket::INET; use IO::Socket::INET;
use IO::Select; use IO::Select;
use File::Basename; use File::Basename;
@ -175,7 +175,13 @@ sub file_set_contents {
my $tmpname = "$filename.tmp.$$"; my $tmpname = "$filename.tmp.$$";
eval { eval {
my $fh = IO::File->new($tmpname, O_WRONLY|O_CREAT, $perm); my ($fh, $tries) = (undef, 0);
while (!$fh && $tries++ < 3) {
$fh = IO::File->new($tmpname, O_WRONLY|O_CREAT|O_EXCL, $perm);
if (!$fh && $! == EEXIST) {
unlink($tmpname) or die "unable to delete old temp file: $!\n";
}
}
die "unable to open file '$tmpname' - $!\n" if !$fh; die "unable to open file '$tmpname' - $!\n" if !$fh;
die "unable to write '$tmpname' - $!\n" unless print $fh $data; die "unable to write '$tmpname' - $!\n" unless print $fh $data;
die "closing file '$tmpname' failed - $!\n" unless close $fh; die "closing file '$tmpname' failed - $!\n" unless close $fh;