file size info: allow specifying file format
Allow callers to opt-out of 'qemu-img' autodetecting the format. Currently not supported to be done together with untrusted, because it can lead to less checks being done. Could be further refined (e.g. disallow only untrusted together with format being 'raw') should the need arise. For 'subvol' format, the checking is handled outside of 'qemu-img' of course, based on whether it is a directory or not. Currently, there is a fallback to 'raw' should the format not be among the ones allowed for the 'pve-qm-image-format' standard option. This is to reduce potential for fallout, in particular for the plan to change the base plugin's volume_size_info() to pass in the expected format when calling file_size_info() too. While not explicitly part of the storage plugin API, the 'untrusted' parameter is now in a different place, so a compat check is added for external plugins that might've still used it. Breaks for qemu-server needed (if we don't want to just rely on the compat check). Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
This commit is contained in:
committed by
Fabian Grünbichler
parent
10d338baa8
commit
83648951d7
@ -63,7 +63,7 @@ sub extract_disk_from_import_file {
|
||||
}
|
||||
|
||||
# check potentially untrusted image file!
|
||||
PVE::Storage::file_size_info($source_path, undef, 1);
|
||||
PVE::Storage::file_size_info($source_path, undef, undef, 1);
|
||||
|
||||
# create temporary 1M image that will get overwritten by the rename
|
||||
# to reserve the filename and take care of locking
|
||||
|
||||
@ -242,9 +242,9 @@ sub storage_ids {
|
||||
}
|
||||
|
||||
sub file_size_info {
|
||||
my ($filename, $timeout, $untrusted) = @_;
|
||||
my ($filename, $timeout, $file_format, $untrusted) = @_;
|
||||
|
||||
return PVE::Storage::Plugin::file_size_info($filename, $timeout, $untrusted);
|
||||
return PVE::Storage::Plugin::file_size_info($filename, $timeout, $file_format, $untrusted);
|
||||
}
|
||||
|
||||
sub get_volume_attribute {
|
||||
@ -2223,7 +2223,7 @@ sub assert_iso_content {
|
||||
my ($path) = @_;
|
||||
|
||||
# check for things like backing image
|
||||
file_size_info($path, undef, 1);
|
||||
file_size_info($path, undef, undef, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -950,13 +950,27 @@ sub free_image {
|
||||
return undef;
|
||||
}
|
||||
|
||||
# TODO taken from PVE/QemuServer/Drive.pm, avoiding duplication would be nice
|
||||
my @checked_qemu_img_formats = qw(raw cow qcow qcow2 qed vmdk cloop);
|
||||
|
||||
# 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)
|
||||
#
|
||||
# Set $file_format to force qemu-img to treat the image as being a specific format.
|
||||
sub file_size_info {
|
||||
my ($filename, $timeout, $untrusted) = @_;
|
||||
my ($filename, $timeout, $file_format, $untrusted) = @_;
|
||||
|
||||
# compat for old parameter order
|
||||
# TODO PVE 9 remove
|
||||
if (defined($file_format) && ($file_format eq '1' || $file_format eq '0')) {
|
||||
warn "file_size_info: detected call with legacy parameter order: \$untrusted before"
|
||||
." \$file_format\n";
|
||||
$untrusted = $file_format;
|
||||
$file_format = undef;
|
||||
}
|
||||
|
||||
my $st = File::stat::stat($filename);
|
||||
|
||||
@ -982,13 +996,24 @@ sub file_size_info {
|
||||
};
|
||||
|
||||
if (S_ISDIR($st->mode)) {
|
||||
$handle_error->("expected format '$file_format', but '$filename' is a directory\n")
|
||||
if $file_format && $file_format ne 'subvol';
|
||||
return wantarray ? (0, 'subvol', 0, undef, $st->ctime) : 1;
|
||||
} elsif ($file_format && $file_format eq 'subvol') {
|
||||
$handle_error->("expected format '$file_format', but '$filename' is not a directory\n");
|
||||
}
|
||||
|
||||
# TODO PVE 9 - consider upgrading to "die" if an unsupported format is passed in after
|
||||
# evaluating breakage potential.
|
||||
$file_format = 'raw' if $file_format && !grep { $_ eq $file_format } @checked_qemu_img_formats;
|
||||
|
||||
my $cmd = ['/usr/bin/qemu-img', 'info', '--output=json', $filename];
|
||||
push $cmd->@*, '-f', $file_format if $file_format;
|
||||
|
||||
my $json = '';
|
||||
my $err_output = '';
|
||||
eval {
|
||||
run_command(['/usr/bin/qemu-img', 'info', '--output=json', $filename],
|
||||
run_command($cmd,
|
||||
timeout => $timeout,
|
||||
outfunc => sub { $json .= shift },
|
||||
errfunc => sub { $err_output .= shift . "\n"},
|
||||
@ -1041,6 +1066,10 @@ sub file_size_info {
|
||||
warn "strange parent name path '$parent' found\n" if $parent =~ m/[^\S]/;
|
||||
($parent) = ($parent =~ /^(\S+)$/); # untaint
|
||||
}
|
||||
|
||||
die "qemu-img bug: queried format does not match format in result '$file_format ne $format'"
|
||||
if $file_format && $file_format ne $format;
|
||||
|
||||
return wantarray ? ($size, $format, $used, $parent, $st->ctime) : $size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user