refactor: move rng related code into its own module

Move code related to VirtIO RNG configuration for a VM to its own
module.

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
This commit is contained in:
Filip Schauer 2025-02-18 12:10:55 +01:00 committed by Fabian Grünbichler
parent 83cf49aa36
commit 18fc321ef3
3 changed files with 89 additions and 58 deletions

View File

@ -61,6 +61,7 @@ use PVE::QemuServer::MetaInfo;
use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port parse_hostpci);
use PVE::QemuServer::QMPHelpers qw(qemu_deviceadd qemu_devicedel qemu_objectadd qemu_objectdel);
use PVE::QemuServer::RNG qw(check_rng_source parse_rng);
use PVE::QemuServer::USB;
my $have_sdn;
@ -256,36 +257,6 @@ my $spice_enhancements_fmt = {
},
};
my $rng_fmt = {
source => {
type => 'string',
enum => ['/dev/urandom', '/dev/random', '/dev/hwrng'],
default_key => 1,
description => "The file on the host to gather entropy from. Using urandom does *not*"
." decrease security in any meaningful way, as it's still seeded from real entropy, and"
." the bytes provided will most likely be mixed with real entropy on the guest as well."
."'/dev/hwrng' can be used to pass through a hardware RNG from the host.",
},
max_bytes => {
type => 'integer',
description => "Maximum bytes of entropy allowed to get injected into the guest every"
." 'period' milliseconds. Use `0` to disable limiting (potentially dangerous!).",
optional => 1,
# default is 1 KiB/s, provides enough entropy to the guest to avoid boot-starvation issues
# (e.g. systemd etc...) while allowing no chance of overwhelming the host, provided we're
# reading from /dev/urandom
default => 1024,
},
period => {
type => 'integer',
description => "Every 'period' milliseconds the entropy-injection quota is reset, allowing"
." the guest to retrieve another 'max_bytes' of entropy.",
optional => 1,
default => 1000,
},
};
my $confdesc = {
onboot => {
optional => 1,
@ -713,7 +684,7 @@ EODESCR
},
rng0 => {
type => 'string',
format => $rng_fmt,
format => 'pve-qm-rng',
description => "Configure a VirtIO-based Random Number Generator.",
optional => 1,
},
@ -1976,16 +1947,6 @@ sub parse_vga {
return $res;
}
sub parse_rng {
my ($value) = @_;
return if !$value;
my $res = eval { parse_property_string($rng_fmt, $value) };
warn $@ if $@;
return $res;
}
sub qemu_created_version_fixups {
my ($conf, $forcemachine, $kvmver) = @_;
@ -4058,23 +4019,6 @@ sub config_to_command {
return wantarray ? ($cmd, $vollist, $spice_port, $pci_devices, $conf) : $cmd;
}
sub check_rng_source {
my ($source) = @_;
# mostly relevant for /dev/hwrng, but doesn't hurt to check others too
die "cannot create VirtIO RNG device: source file '$source' doesn't exist\n"
if ! -e $source;
my $rng_current = '/sys/devices/virtual/misc/hw_random/rng_current';
if ($source eq '/dev/hwrng' && file_read_firstline($rng_current) eq 'none') {
# Needs to abort, otherwise QEMU crashes on first rng access. Note that rng_current cannot
# be changed to 'none' manually, so once the VM is past this point, it's no longer an issue.
die "Cannot start VM with passed-through RNG device: '/dev/hwrng' exists, but"
." '$rng_current' is set to 'none'. Ensure that a compatible hardware-RNG is attached"
." to the host.\n";
}
}
sub spice_port {
my ($vmid) = @_;

View File

@ -1,4 +1,5 @@
SOURCES=PCI.pm \
RNG.pm \
USB.pm \
Memory.pm \
ImportDisk.pm \

86
PVE/QemuServer/RNG.pm Normal file
View File

@ -0,0 +1,86 @@
package PVE::QemuServer::RNG;
use strict;
use warnings;
use PVE::JSONSchema;
use PVE::Tools qw(file_read_firstline);
use PVE::QemuServer::PCI qw(print_pci_addr);
use base 'Exporter';
our @EXPORT_OK = qw(
parse_rng
check_rng_source
);
my $rng_fmt = {
source => {
type => 'string',
enum => ['/dev/urandom', '/dev/random', '/dev/hwrng'],
default_key => 1,
description => "The file on the host to gather entropy from. Using urandom does *not*"
." decrease security in any meaningful way, as it's still seeded from real entropy, and"
." the bytes provided will most likely be mixed with real entropy on the guest as well."
." '/dev/hwrng' can be used to pass through a hardware RNG from the host.",
},
max_bytes => {
type => 'integer',
description => "Maximum bytes of entropy allowed to get injected into the guest every"
." 'period' milliseconds. Use `0` to disable limiting (potentially dangerous!).",
optional => 1,
# default is 1 KiB/s, provides enough entropy to the guest to avoid boot-starvation issues
# (e.g. systemd etc...) while allowing no chance of overwhelming the host, provided we're
# reading from /dev/urandom
default => 1024,
},
period => {
type => 'integer',
description => "Every 'period' milliseconds the entropy-injection quota is reset, allowing"
." the guest to retrieve another 'max_bytes' of entropy.",
optional => 1,
default => 1000,
},
};
PVE::JSONSchema::register_format('pve-qm-rng', $rng_fmt);
our $rngdesc = {
type => 'string',
format => $rng_fmt,
optional => 1,
description => "Configure a VirtIO-based Random Number Generator.",
};
PVE::JSONSchema::register_standard_option('pve-qm-rng', $rngdesc);
sub parse_rng {
my ($value) = @_;
return if !$value;
my $res = eval { PVE::JSONSchema::parse_property_string($rng_fmt, $value) };
warn $@ if $@;
return $res;
}
sub check_rng_source {
my ($source) = @_;
# mostly relevant for /dev/hwrng, but doesn't hurt to check others too
die "cannot create VirtIO RNG device: source file '$source' doesn't exist\n"
if ! -e $source;
my $rng_current = '/sys/devices/virtual/misc/hw_random/rng_current';
if ($source eq '/dev/hwrng' && file_read_firstline($rng_current) eq 'none') {
# Needs to abort, otherwise QEMU crashes on first rng access. Note that rng_current cannot
# be changed to 'none' manually, so once the VM is past this point, it's no longer an issue.
die "Cannot start VM with passed-through RNG device: '/dev/hwrng' exists, but"
." '$rng_current' is set to 'none'. Ensure that a compatible hardware-RNG is attached"
." to the host.\n";
}
}
1;