all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>,
	Filip Schauer <f.schauer@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server v2 7/9] refactor: move rng related code into its own module
Date: Thu, 30 Jan 2025 13:17:53 +0100	[thread overview]
Message-ID: <7dc786fe-6238-4033-8c06-b7511c45c244@proxmox.com> (raw)
In-Reply-To: <20250129155339.164696-8-f.schauer@proxmox.com>

Am 29.01.25 um 16:53 schrieb Filip Schauer:
> Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
> ---
>  PVE/QemuServer.pm       |  83 +++---------------------
>  PVE/QemuServer/Makefile |   1 +
>  PVE/QemuServer/RNG.pm   | 135 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 145 insertions(+), 74 deletions(-)
>  create mode 100644 PVE/QemuServer/RNG.pm
> 
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 5cde94a1..93e65825 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -61,6 +61,7 @@ use PVE::QemuServer::Memory qw(get_current_memory);
>  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;
>  use PVE::QemuServer::USB;
>  
>  my $have_sdn;
> @@ -249,39 +250,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. In most cases '/dev/urandom'"
> -	    ." should be preferred over '/dev/random' to avoid entropy-starvation issues on the"
> -	    ." host. 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. Prefer a lower value when using '/dev/random' as source. 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 $meta_info_fmt = {
>      'ctime' => {
>  	type => 'integer',

Does not apply, because this got moved recently ;)

> @@ -724,7 +692,7 @@ EODESCR
>      },
>      rng0 => {
>  	type => 'string',
> -	format => $rng_fmt,
> +	format => $PVE::QemuServer::RNG::rng_fmt,
>  	description => "Configure a VirtIO-based Random Number Generator.",
>  	optional => 1,
>      },

Could instead use the standard option you define in the RNG module.

> @@ -2078,16 +2046,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 parse_meta_info {
>      my ($value) = @_;
> 

Does not apply, because this got moved recently ;)

> @@ -3940,20 +3898,14 @@ sub config_to_command {
>  	}
>      }
>  
> -    my $rng = $conf->{rng0} ? parse_rng($conf->{rng0}) : undef;
> +    my $rng = $conf->{rng0} ? PVE::QemuServer::RNG::parse_rng($conf->{rng0}) : undef;
>      if ($rng && $version_guard->(4, 1, 2)) {
> -	check_rng_source($rng->{source});
> -
> -	my $max_bytes = $rng->{max_bytes} // $rng_fmt->{max_bytes}->{default};
> -	my $period = $rng->{period} // $rng_fmt->{period}->{default};
> -	my $limiter_str = "";
> -	if ($max_bytes) {
> -	    $limiter_str = ",max-bytes=$max_bytes,period=$period";
> -	}
> -
> -	my $rng_addr = print_pci_addr("rng0", $bridges, $arch, $machine_type);
> -	push @$devices, '-object', "rng-random,filename=$rng->{source},id=rng0";
> -	push @$devices, '-device', "virtio-rng-pci,rng=rng0$limiter_str$rng_addr";
> +	my $rng_object = PVE::QemuServer::RNG::print_rng_object('rng0', $rng);
> +	my $rng_device = PVE::QemuServer::RNG::print_rng_device(
> +	    'rng0', $rng, $bridges, $arch, $machine_type
> +	);

Style nit: that's not how multiline function calls are usually wrapped
in our Perl code base:
https://pve.proxmox.com/wiki/Perl_Style_Guide#Wrapping_Arguments

> +	push @$devices, '-object', $rng_object;
> +	push @$devices, '-device', $rng_device;
>      }
>  
>      my $spice_port;

Would be nice to have the moving to a dedicated module be separate from
adding the new helpers.

> @@ -4235,23 +4187,6 @@ sub config_to_command {
>      return wantarray ? ($cmd, $vollist, $spice_port, $pci_devices) : $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) = @_;
>  
> diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
> index 89d12091..72c287fc 100644
> --- a/PVE/QemuServer/Makefile
> +++ b/PVE/QemuServer/Makefile
> @@ -1,4 +1,5 @@
>  SOURCES=PCI.pm		\
> +	RNG.pm		\
>  	USB.pm		\
>  	Memory.pm	\
>  	ImportDisk.pm	\
> diff --git a/PVE/QemuServer/RNG.pm b/PVE/QemuServer/RNG.pm
> new file mode 100644
> index 00000000..f7a62f3b
> --- /dev/null
> +++ b/PVE/QemuServer/RNG.pm
> @@ -0,0 +1,135 @@
> +package PVE::QemuServer::RNG;
> +
> +use strict;
> +use warnings;
> +
> +use PVE::QemuServer::PCI qw(print_pci_addr);
> +use PVE::JSONSchema;
> +use PVE::Tools qw(file_read_firstline);
> +use base 'Exporter';

Style nit: The QemuServer::PCI module should be grouped below and I'd
prefer having a blank before it:
https://lore.proxmox.com/pve-devel/e24881cf-bfd2-4063-bde2-99f41031f0f0@proxmox.com/
Having the 'use base' be last is fine, but I'd also prefer a blank
before it.

> +
> +our @EXPORT_OK = qw(
> +parse_rng
> +check_rng_source
> +print_rng_device
> +print_rng_object
> +);
> +
> +our $rng_fmt = {
> +    source => {
> +	type => 'string',
> +	enum => ['/dev/urandom', '/dev/random', '/dev/hwrng'],
> +	default_key => 1,
> +	optional => 1,

Adding the optional should not be part of this patch.

> +	description => "The file on the host to gather entropy from. In most cases '/dev/urandom'"
> +	    ." should be preferred over '/dev/random' to avoid entropy-starvation issues on the"
> +	    ." host. 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.",

The part about /dev/random is outdated as you pointed out in v1 ;)

> +    },
> +    max_bytes => {
> +	type => 'integer',
> +	description => "Maximum bytes of entropy allowed to get injected into the guest every"
> +	    ." 'period' milliseconds. Prefer a lower value when using '/dev/random' as source. Use"
> +	    ." `0` to disable limiting (potentially dangerous!).",


The part about /dev/random is outdated as you pointed out in v1 ;)

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

Since you register the format here, you don't need to make $rng_fmt
shared with 'our' or? (Still need to include the module in QemuServer.pm
to have registering come first).

> +
> +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 $@;
> +
> +    my $source = $res->{source};

Unused variable, should be part of a later patch.

> +
> +    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";
> +    }
> +}
> +
> +sub get_rng_source_path {
> +    my ($rng) = @_;
> +
> +    my $source = $rng->{source};
> +
> +    if (defined($source)) {
> +	return $source;
> +    }
> +
> +    return;
> +}
> +
> +sub print_rng_device {

I'd add _commandline to reduce potential for confusion

> +    my ($id, $rng, $bridges, $arch, $machine) = @_;
> +
> +    return if !$rng;

Isn't failing better? IMHO caller should first check that it has
something to print rather than check the result.

> +
> +    my $source_path = get_rng_source_path($rng);
> +    check_rng_source($source_path);

Since the source is not part of the result, maybe not check it here, but
only in print_rng_object()?

> +
> +    my $max_bytes = $rng->{max_bytes} // $rng_fmt->{max_bytes}->{default};
> +    my $period = $rng->{period} // $rng_fmt->{period}->{default};
> +    my $limiter_str = "";
> +    if ($max_bytes) {
> +	$limiter_str = ",max-bytes=$max_bytes,period=$period";
> +    }
> +
> +    my $rng_addr = print_pci_addr($id, $bridges, $arch, $machine);
> +
> +    return "virtio-rng-pci,rng=$id$limiter_str$rng_addr";
> +}
> +
> +sub print_rng_object {

I'd add _commandline to reduce potential for confusion

> +    my ($id, $rng) = @_;
> +
> +    return if !$rng;

Isn't failing better? IMHO caller should first check that it has
something to print rather than check the result.

> +
> +    my $source_path = get_rng_source_path($rng);
> +    check_rng_source($source_path);
> +
> +    return "rng-random,filename=$source_path,id=$id";
> +}
> +
> +1;



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  reply	other threads:[~2025-01-30 12:17 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-29 15:53 [pve-devel] [PATCH cluster/guest-common/manager/qemu-server v2 0/9] fix #5657: allow configuring RNG device as non-root user Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH guest-common v2 1/9] mapping: add a hardware RNG mapping config Filip Schauer
2025-01-30 12:18   ` Fiona Ebner
2025-01-29 15:53 ` [pve-devel] [PATCH cluster v2 2/9] cfs: add 'mapping/hwrng.cfg' to observed files Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH manager v2 3/9] introduce hardware rng mapping api Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH manager v2 4/9] introduce hardware rng scanning api Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH manager v2 5/9] ui: add hardware RNG resource mapping Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH manager v2 6/9] ui: allow use of mapped hardware RNGs as entropy sources for VMs Filip Schauer
2025-01-29 15:53 ` [pve-devel] [PATCH qemu-server v2 7/9] refactor: move rng related code into its own module Filip Schauer
2025-01-30 12:17   ` Fiona Ebner [this message]
2025-01-29 15:53 ` [pve-devel] [PATCH qemu-server v2 8/9] allow non-root users to set /dev/u?random as an RNG source Filip Schauer
2025-01-30 12:18   ` Fiona Ebner
2025-01-29 15:53 ` [pve-devel] [PATCH qemu-server v2 9/9] let VirtIO RNG devices source entropy from mapped HWRNGs Filip Schauer
2025-01-30 12:17 ` [pve-devel] [PATCH cluster/guest-common/manager/qemu-server v2 0/9] fix #5657: allow configuring RNG device as non-root user Fiona Ebner
2025-02-10 15:47   ` Filip Schauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7dc786fe-6238-4033-8c06-b7511c45c244@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=f.schauer@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal