this allows checking some extra attributes for images which come from a potentially malicious source.
since file_size_info is not part of the plugin API, no API bump is needed. if desired, a similar check could also be implemented in volume_size_info, which would entail bumping both APIVER and APIAGE (since the additional parameter would make checking untrusted volumes opt-in for external plugins). Signed-off-by: Fabian Grünbichler <f.gruenbich...@proxmox.com> --- src/PVE/Storage.pm | 4 ++-- src/PVE/Storage/Plugin.pm | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm index 57b2038..3f0b9ae 100755 --- a/src/PVE/Storage.pm +++ b/src/PVE/Storage.pm @@ -233,9 +233,9 @@ sub storage_ids { } sub file_size_info { - my ($filename, $timeout) = @_; + my ($filename, $timeout, $untrusted) = @_; - return PVE::Storage::Plugin::file_size_info($filename, $timeout); + return PVE::Storage::Plugin::file_size_info($filename, $timeout, $untrusted); } sub get_volume_attribute { diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm index 6444390..b03e183 100644 --- a/src/PVE/Storage/Plugin.pm +++ b/src/PVE/Storage/Plugin.pm @@ -943,15 +943,25 @@ sub free_image { return undef; } +# set $untrusted if the file in question might be malicious since it isn't +# created by our stack +# this makes certain checks fatal, and adds extra checks for known problems like +# - backing files (qcow2/vmdk) +# - external data files (qcow2) sub file_size_info { - my ($filename, $timeout) = @_; + my ($filename, $timeout, $untrusted) = @_; my $st = File::stat::stat($filename); if (!defined($st)) { my $extramsg = -l $filename ? ' - dangling symlink?' : ''; - warn "failed to stat '$filename'$extramsg\n"; - return undef; + my $msg = "failed to stat '$filename'$extramsg\n"; + if ($untrusted) { + die $msg; + } else { + warn $msg; + return undef; + } } if (S_ISDIR($st->mode)) { @@ -977,12 +987,27 @@ sub file_size_info { my $info = eval { decode_json($json) }; if (my $err = $@) { - warn "could not parse qemu-img info command output for '$filename' - $err\n"; - return wantarray ? (undef, undef, undef, undef, $st->ctime) : undef; + my $msg = "could not parse qemu-img info command output for '$filename' - $err\n"; + if ($untrusted) { + die $msg; + } else { + warn $msg; + return wantarray ? (undef, undef, undef, undef, $st->ctime) : undef; + } + } + + if ($untrusted) { + if (my $format_specific = $info->{'format-specific'}) { + if ($format_specific->{type} eq 'qcow2' && $format_specific->{data}->{"data-file"}) { + die "$filename: 'data-file' references are not allowed!\n"; + } + } } my ($size, $format, $used, $parent) = $info->@{qw(virtual-size format actual-size backing-filename)}; + die "backing file not allowed for untrusted image '$filename'!\n" if $untrusted && $parent; + ($size) = ($size =~ /^(\d+)$/); # untaint die "size '$size' not an integer\n" if !defined($size); # coerce back from string -- 2.39.2 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel