[pve-devel] [PATCH v3 qemu-server 08/12] Verify VM-specific CPU configs seperately
Stefan Reiter
s.reiter at proxmox.com
Tue Oct 15 16:12:30 CEST 2019
$cpu_fmt is being reused for custom CPUs as well as VM-specific CPU
settings. The "pve-vm-cpu-conf" format is introduced to verify a config
specifically for use as VM-specific settings.
"pve-cpu-conf" is registered for use in custom CPU API calls (where no
additional checks are required).
Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
v4 -> v5:
* extract both regexes into vars
* add 'pve-cpu-conf' format for future use
* rename verify_vm_cpu_conf to parse_vm_cpu_conf (since it's used for parsing in
a later patch, and also to make it consistent with parse_cpu_conf_basic)
* fix VM-specific CPU verification to also be applied with custom models
v3 -> v4:
* use is_custom_model
v2 -> v3:
* move $cpu_fmt->{flags} changes here, to avoid having broken checks between
patches
PVE/QemuServer.pm | 2 +-
PVE/QemuServer/CPUConfig.pm | 73 ++++++++++++++++++++++++++++++++++---
2 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index e7758cb..874137f 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -505,7 +505,7 @@ EODESCR
optional => 1,
description => "Emulated CPU type.",
type => 'string',
- format => $PVE::QemuServer::CPUConfig::cpu_fmt,
+ format => 'pve-vm-cpu-conf',
},
parent => get_standard_option('pve-snapshot-name', {
optional => 1,
diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index 2a65d50..ed883e1 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -90,9 +90,10 @@ my @supported_cpu_flags = (
'hv-evmcs',
'aes'
);
-my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/;
+my $cpu_flag_supported_re = qr/([+-])(@{[join('|', @supported_cpu_flags)]})/;
+my $cpu_flag_any_re = qr/([+-])([a-zA-Z0-9\-_\.]+)/;
-our $cpu_fmt = {
+my $cpu_fmt = {
cputype => {
description => "Emulated CPU type. Can be default or custom name (custom model names must be prefixed with 'custom-').",
type => 'string',
@@ -125,14 +126,76 @@ our $cpu_fmt = {
flags => {
description => "List of additional CPU flags separated by ';'."
. " Use '+FLAG' to enable, '-FLAG' to disable a flag."
- . " Currently supported flags: @{[join(', ', @supported_cpu_flags)]}.",
+ . " Custom CPU models can specify any flag supported by"
+ . " QEMU/KVM, VM-specific flags must be from the following"
+ . " set for security reasons: @{[join(', ', @supported_cpu_flags)]}.",
format_description => '+FLAG[;-FLAG...]',
type => 'string',
- pattern => qr/$cpu_flag(;$cpu_flag)*/,
+ pattern => qr/$cpu_flag_any_re(;$cpu_flag_any_re)*/,
optional => 1,
},
};
+# $cpu_fmt describes both the CPU config passed as part of a VM config, as well
+# as the definition of a custom CPU model. There are some slight differences
+# though, which we catch in the custom verification function below.
+PVE::JSONSchema::register_format('pve-cpu-conf', \&parse_cpu_conf_basic);
+sub parse_cpu_conf_basic {
+ my ($cpu_str, $noerr) = @_;
+
+ my $cpu = eval { PVE::JSONSchema::parse_property_string($cpu_fmt, $cpu_str) };
+ if ($@) {
+ die $@ if !$noerr;
+ return undef;
+ }
+
+ # required, but can't be forced in schema since it's encoded in section
+ # header for custom models
+ if (!$cpu->{cputype}) {
+ die "CPU is missing cputype\n" if !$noerr;
+ return undef;
+ }
+
+ return $cpu;
+}
+
+PVE::JSONSchema::register_format('pve-vm-cpu-conf', \&parse_vm_cpu_conf);
+sub parse_vm_cpu_conf {
+ my ($cpu_str, $noerr) = @_;
+
+ my $cpu = parse_cpu_conf_basic($cpu_str, $noerr);
+ return undef if !$cpu;
+
+ my $cputype = $cpu->{cputype};
+
+ # a VM-specific config is only valid if the cputype exists
+ if (is_custom_model($cputype)) {
+ eval { get_custom_model($cputype); };
+ if ($@) {
+ die $@ if !$noerr;
+ return undef;
+ }
+ } else {
+ if (!defined($cpu_vendor_list->{$cputype})) {
+ die "Built-in cputype '$cputype' is not defined (missing 'custom-' prefix?)\n" if !$noerr;
+ return undef;
+ }
+ }
+
+ # in a VM-specific config, certain properties are limited/forbidden
+
+ if ($cpu->{flags} && $cpu->{flags} !~ m/$cpu_flag_supported_re(;$cpu_flag_supported_re)*/) {
+ die "VM-specific CPU flags must be a subset of: @{[join(', ', @supported_cpu_flags)]}\n"
+ if !$noerr;
+ return undef;
+ }
+
+ die "Property 'reported-model' not allowed in VM-specific CPU config.\n"
+ if defined($cpu->{'reported-model'});
+
+ return $cpu;
+}
+
# Section config settings
my $defaultData = {
# shallow copy, since SectionConfig modifies propertyList internally
@@ -220,7 +283,7 @@ sub print_cpu_device {
my $kvm = $conf->{kvm} // 1;
my $cpu = $kvm ? "kvm64" : "qemu64";
if (my $cputype = $conf->{cpu}) {
- my $cpuconf = PVE::JSONSchema::parse_property_string($cpu_fmt, $cputype)
+ my $cpuconf = parse_cpu_conf_basic($cputype)
or die "Cannot parse cpu description: $cputype\n";
$cpu = $cpuconf->{cputype};
}
--
2.20.1
More information about the pve-devel
mailing list