[pve-devel] [PATCH container] create: fix passing of template file descriptor

Thomas Lamprecht t.lamprecht at proxmox.com
Tue Mar 20 09:49:53 CET 2018


On 3/20/18 9:32 AM, Wolfgang Bumiller wrote:
> 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...)

cheeky GNU tar ...

> Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
> ---
>  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";

A mapping (defined a bit above) would be maybe nicer to read? 

my $compressions = {
    '.gz' => '-z',
    ...
};

But at least you made it look symmetric :)

Looks OK:

Reviewed-by: Thomas Lamprecht <t.lamprecht at proxmox.com>

> +	    }
> +	} 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;
> 




More information about the pve-devel mailing list