]> git.proxmox.com Git - pve-common.git/commitdiff
harden file_set_contents against symlink attacks
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Tue, 16 Aug 2016 14:31:10 +0000 (16:31 +0200)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Tue, 16 Aug 2016 14:41:15 +0000 (16:41 +0200)
data/PVE/Tools.pm

index 827ca58bcfec494e823b6d957599966f6b548ce7..4c9a49efa8ae6163634e3132b9514ec1c5e2610e 100644 (file)
@@ -2,7 +2,7 @@ package PVE::Tools;
 
 use strict;
 use warnings;
-use POSIX qw(EINTR);
+use POSIX qw(EINTR EEXIST);
 use IO::Socket::INET;
 use IO::Select;
 use File::Basename;
@@ -175,7 +175,13 @@ sub file_set_contents {
     my $tmpname = "$filename.tmp.$$";
 
     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 write '$tmpname' - $!\n" unless print $fh $data;
        die "closing file '$tmpname' failed - $!\n" unless close $fh;