summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
63231f5)
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 <w.bumiller@proxmox.com>
my $userns_cmd = PVE::LXC::userns_command($id_map);
my $archive_fh;
my $userns_cmd = PVE::LXC::userns_command($id_map);
my $archive_fh;
- my $tar_input_file = '-';
+ my $tar_input = '<&STDIN';
+ my @compression_opt;
+ # GNU tar refuses to autodetect this... *sigh*
+ my %compression_map = (
+ '.gz' => '-z',
+ '.bz2' => '-j',
+ '.xz' => '-J',
+ );
+ if ($archive =~ /\.tar(\.[^.]+)?$/) {
+ if (defined($1)) {
+ @compression_opt = $compression_map{$1}
+ or 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";
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()));
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];
@PVE::Storage::Plugin::COMMON_TAR_FLAGS,
'-C', $rootdir];
if ($archive eq '-') {
print "extracting archive from STDIN\n";
if ($archive eq '-') {
print "extracting archive from STDIN\n";
- eval { PVE::Tools::run_command($cmd, input => "<&STDIN"); };
} else {
print "extracting archive '$archive'\n";
} 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;
my $err = $@;
close($archive_fh) if defined $archive_fh;
die $err if $err && !$no_unpack_error;