]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
tools: load direct kernel config from libvirt
authorDaniel P. Berrangé <berrange@redhat.com>
Thu, 6 Oct 2022 11:35:40 +0000 (12:35 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Tue, 15 Nov 2022 11:09:30 +0000 (11:09 +0000)
When connected to libvirt we can validate that the guest configuration
has the kernel hashes property enabled, otherwise including the kernel
GUID table in our expected measurements is not likely to match the
actual measurement.

When running locally we can also automatically detect the kernel/initrd
paths, along with the cmdline string from the XML.

Reviewed-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
docs/manpages/virt-qemu-sev-validate.rst
tools/virt-qemu-sev-validate

index e8a868f5a83192d924dda34d4293faf3f424475b..e374fecec0d6b55ac9bf55b802018aeca41a9a83 100644 (file)
@@ -265,6 +265,15 @@ Validate the measurement of a SEV guest booting from disk:
        --tk this-guest-tk.bin \
        --domain fedora34x86_64
 
+Validate the measurement of a SEV guest with direct kernel boot:
+
+::
+
+   # virt-dom-sev-validate \
+       --insecure \
+       --tk this-guest-tk.bin \
+       --domain fedora34x86_64
+
 EXIT STATUS
 ===========
 
index b978c3eb3d9ef76cc869732ff2e86895cae85f74..301660ba8e7372a5e712dd2cb5ccdfe6e5e70e52 100755 (executable)
@@ -300,6 +300,35 @@ class LibvirtConfidentialVM(ConfidentialVM):
             raise IncorrectConfigException(
                 "Domain must have one firmware path")
 
+        measure_kernel_nodes = doc.xpath(
+            "/domain/launchSecurity[@type='sev']/@kernelHashes")
+        measure_kernel = False
+        if len(measure_kernel_nodes) == 1:
+            if measure_kernel_nodes[0] == "yes":
+                measure_kernel = True
+
+        xp_kernel = "/domain/os/kernel"
+        xp_initrd = "/domain/os/initrd"
+        xp_cmdline = "/domain/os/cmdline"
+        kern_nodes = (doc.xpath(xp_kernel) +
+                      doc.xpath(xp_initrd) +
+                      doc.xpath(xp_cmdline))
+        if not measure_kernel:
+            if len(self.kernel_table.entries()) != 0:
+                raise UnsupportedUsageException(
+                    "kernel/initrd/cmdline provided but kernel "
+                    "measurement not enabled")
+
+            # Check for an insecure scenario
+            if len(kern_nodes) != 0 and secure:
+                raise InsecureUsageException(
+                    "direct kernel boot present without measurement")
+        else:
+            if len(kern_nodes) == 0:
+                raise IncorrectConfigException(
+                    "kernel/initrd/cmdline not provided but kernel "
+                    "measurement is enabled")
+
     def load_domain(self, uri, id_name_uuid, secure, ignore_config):
         self.conn = libvirt.open(uri)
 
@@ -368,6 +397,36 @@ class LibvirtConfidentialVM(ConfidentialVM):
 
             self.load_firmware(loadernodes[0].text)
 
+        if self.kernel_table.kernel is None:
+            kernelnodes = doc.xpath("/domain/os/kernel")
+            if len(kernelnodes) != 0:
+                if remote:
+                    raise UnsupportedUsageException(
+                        "Cannot access kernel path remotely")
+                if secure:
+                    raise InsecureUsageException(
+                        "Using kernel path from XML is not secure")
+                self.kernel_table.load_kernel(kernelnodes[0].text)
+
+        if self.kernel_table.initrd is None:
+            initrdnodes = doc.xpath("/domain/os/initrd")
+            if len(initrdnodes) != 0:
+                if remote:
+                    raise UnsupportedUsageException(
+                        "Cannot access initrd path remotely")
+                if secure:
+                    raise InsecureUsageException(
+                        "Using initrd path from XML is not secure")
+                self.kernel_table.load_initrd(initrdnodes[0].text)
+
+        if self.kernel_table.cmdline is None:
+            cmdlinenodes = doc.xpath("/domain/os/cmdline")
+            if len(cmdlinenodes) != 0:
+                if secure:
+                    raise InsecureUsageException(
+                        "Using cmdline string from XML is not secure")
+                self.kernel_table.load_cmdline(cmdlinenodes[0].text)
+
 
 def parse_command_line():
     parser = argparse.ArgumentParser(