From aa757172c65a2d60382905c291184bbeed3ae484 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Tue, 16 Aug 2016 16:31:10 +0200 Subject: [PATCH] harden file_set_contents against symlink attacks --- data/PVE/Tools.pm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/PVE/Tools.pm b/data/PVE/Tools.pm index 827ca58..4c9a49e 100644 --- a/data/PVE/Tools.pm +++ b/data/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::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;