This finishes the work started with 07084526aa4a ("create:
open templates as real root"), which opened templates as
real root, but passed it to tar via /proc/*/fd, which does
not actually bypass the check. (Curiously tar did manage to
figure out the file extension from it).In order to actually extract templates the unprivileged user cannot access by themselves, we need to pass it to tar via stdin, however, this means tar cannot auto-detect the compression (or more accurately, it can and does, but tells you which option to pass it rather than just extracting it...) Signed-off-by: Wolfgang Bumiller <[email protected]> --- src/PVE/LXC/Create.pm | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm index 2a37d93..128ede9 100644 --- a/src/PVE/LXC/Create.pm +++ b/src/PVE/LXC/Create.pm @@ -65,16 +65,28 @@ sub restore_archive { my $userns_cmd = PVE::LXC::userns_command($id_map); my $archive_fh; - my $tar_input_file = '-'; + my $tar_input = '<&STDIN'; + my @compression_opt; if ($archive ne '-') { + # GNU tar refuses to autodetect this... *sigh* + if ($archive =~ /\.tar(\.[^.]+)?$/) { + if (defined($1)) { + @compression_opt = $1 eq '.gz' ? ('-z') : + $1 eq '.bz2' ? ('-j') : + $1 eq '.xz' ? ('-J') : + die "unrecognized compression format: $1\n"; + } + } else { + die "file does not look like a template archive: $archive\n"; + } sysopen($archive_fh, $archive, O_RDONLY) or die "failed to open '$archive': $!\n"; - $tar_input_file = '/proc/self/fd/'.fileno($archive_fh); my $flags = $archive_fh->fcntl(Fcntl::F_GETFD(), 0); $archive_fh->fcntl(Fcntl::F_SETFD(), $flags & ~(Fcntl::FD_CLOEXEC())); + $tar_input = '<&'.fileno($archive_fh); } - my $cmd = [@$userns_cmd, 'tar', 'xpf', $tar_input_file, '--totals', + my $cmd = [@$userns_cmd, 'tar', 'xpf', '-', @compression_opt, '--totals', @PVE::Storage::Plugin::COMMON_TAR_FLAGS, '-C', $rootdir]; @@ -88,11 +100,10 @@ sub restore_archive { if ($archive eq '-') { print "extracting archive from STDIN\n"; - eval { PVE::Tools::run_command($cmd, input => "<&STDIN"); }; } else { print "extracting archive '$archive'\n"; - eval { PVE::Tools::run_command($cmd); }; } + eval { PVE::Tools::run_command($cmd, input => $tar_input); }; my $err = $@; close($archive_fh) if defined $archive_fh; die $err if $err && !$no_unpack_error; -- 2.11.0 _______________________________________________ pve-devel mailing list [email protected] https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
