This allows a user with the Mapping.Modify privilege on /mapping/hwrng
to configure a hardware RNG mapping. A less privileged user with the
Mapping.Use privilege can then pass the mapped hardware RNG device as an
entropy source to a VirtIO RNG device.

Signed-off-by: Filip Schauer <f.scha...@proxmox.com>
---
 PVE/API2/Qemu.pm      |  5 +++++
 PVE/QemuServer.pm     |  5 +++++
 PVE/QemuServer/RNG.pm | 25 +++++++++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 194e6357..33b3625b 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -812,9 +812,14 @@ my sub check_rng_perm {
 
     my $device = PVE::JSONSchema::parse_property_string('pve-qm-rng', $value);
     if ($device->{source}) {
+       # Backward compatibility for non-mapped /dev/hwrng
        if ($device->{source} eq '/dev/hwrng') {
            die "only root can set '$opt' config for a non-mapped Hardware RNG 
device\n";
        }
+    } elsif ($device->{mapping}) {
+       $rpcenv->check_full($authuser, "/mapping/hwrng/$device->{mapping}", 
['Mapping.Use']);
+    } else {
+       die "either 'source' or 'mapping' must be set.\n";
     }
 
     return 1;
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index cc69eeb1..82a6c65d 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -6402,10 +6402,15 @@ sub check_mapping_access {
            my $device = PVE::JSONSchema::parse_property_string('pve-qm-rng', 
$conf->{$opt});
 
            if ($device->{source}) {
+               # Backward compatibility for non-mapped /dev/hwrng
                if ($device->{source} eq '/dev/hwrng') {
                    die "only root can set '$opt' config for a non-mapped 
Hardware RNG device\n"
                        if $user ne 'root@pam';
                }
+           } elsif ($device->{mapping}) {
+               $rpcenv->check_full($user, "/mapping/hwrng/$device->{mapping}", 
['Mapping.Use']);
+           } else {
+               die "either 'source' or 'mapping' must be set.\n";
            }
        }
     }
diff --git a/PVE/QemuServer/RNG.pm b/PVE/QemuServer/RNG.pm
index ae5b2530..3ee19852 100644
--- a/PVE/QemuServer/RNG.pm
+++ b/PVE/QemuServer/RNG.pm
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use PVE::JSONSchema;
+use PVE::Mapping::HWRNG;
 use PVE::Tools qw(file_read_firstline);
 
 use PVE::QemuServer::PCI qw(print_pci_addr);
@@ -22,11 +23,20 @@ my $rng_fmt = {
        type => 'string',
        enum => ['/dev/urandom', '/dev/random', '/dev/hwrng'],
        default_key => 1,
+       optional => 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.",
     },
+    mapping => {
+       optional => 1,
+       type => 'string',
+       format_description => 'mapping-id',
+       format => 'pve-configid',
+       description => "The ID of a cluster wide mapping. When specified, 
entropy is gathered from"
+           ." a hardware RNG on the host. Either this or the default-key 
'source' must be set.",
+    },
     max_bytes => {
        type => 'integer',
        description => "Maximum bytes of entropy allowed to get injected into 
the guest every"
@@ -65,6 +75,11 @@ sub parse_rng {
     my $res = eval { PVE::JSONSchema::parse_property_string($rng_fmt, $value) 
};
     warn $@ if $@;
 
+    my $source = $res->{source};
+    my $mapping = $res->{mapping};
+
+    return if $source && $mapping; # not a valid configuration
+
     return $res;
 }
 
@@ -89,9 +104,19 @@ sub get_rng_source_path {
     my ($rng) = @_;
 
     my $source = $rng->{source};
+    my $mapping = $rng->{mapping};
+
+    return if $source && $mapping; # not a valid configuration
 
     if (defined($source)) {
        return $source;
+    } elsif (defined($mapping)) {
+       my $devices = PVE::Mapping::HWRNG::find_on_current_node($mapping);
+       die "Hardware RNG mapping not found for '$mapping'\n" if !$devices || 
!scalar($devices->@*);
+       die "More than one Hardware RNG mapping per host not supported\n"
+           if scalar($devices->@*) > 1;
+
+       return $devices->[0]->{path};
     }
 
     return;
-- 
2.39.5



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

Reply via email to