From: Wolfgang Bumiller Date: Tue, 16 Aug 2016 14:31:09 +0000 (+0200) Subject: harden file_set_contents against symlink attacks X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=commitdiff_plain;h=ce338f4fbc5496fb5efad57f205ed803321902aa;hp=88a490ff71d5491b2564f4f49931e71410bed9c3 harden file_set_contents against symlink attacks --- diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index 0fb7f3c..7ee3450 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -2,7 +2,7 @@ package PVE::Tools; use strict; use warnings; -use POSIX qw(EINTR); +use POSIX qw(EINTR EEXIST); use IO::Socket::IP; use Socket qw(AF_INET AF_INET6 AI_ALL AI_V4MAPPED); use IO::Select; @@ -203,7 +203,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;