[PATCH virt-manager v2] Add support for enabling Secure Encrypted Virtualization in the GUI

Charles Arnold carnold at suse.com
Thu Apr 7 19:14:05 UTC 2022


 From 9646a5dd083a5acdf6cf519863354efaf4bdd07c Mon Sep 17 00:00:00 2001
From: Charles Arnold <carnold at suse.com>
Date: Thu, 7 Apr 2022 13:00:10 -0600
Subject: [PATCH v2 1/1] Add support for enabling Secure Encrypted 
Virtualization
  in the GUI

Add an "Enable launch security" checkbox on the Details memory tab.
Do the minimal configuration required for libvirt to enable this feature
on compatible hardware.

Allow libvirt to determine the firmware file. This just requires
enabling of efi and setting an appropriate policy. Check the libvirt
domain capabilities to determine whether SEV or SEV-ES is supported.

Signed-off-by: Charles Arnold <carnold at suse.com>
---
  ui/details.ui                      | 15 ++++++++++++++-
  virtManager/details/details.py     | 15 ++++++++++++++-
  virtManager/object/domain.py       | 14 +++++++++++++-
  virtinst/domain/launch_security.py | 23 +++++++++++++++--------
  virtinst/domain/memorybacking.py   |  3 +++
  virtinst/domcapabilities.py        |  8 +++++++-
  6 files changed, 66 insertions(+), 12 deletions(-)

diff --git a/ui/details.ui b/ui/details.ui
index 10b30824..b86db275 100644
--- a/ui/details.ui
+++ b/ui/details.ui
@@ -1925,7 +1925,20 @@
                                    </packing>
                                  </child>
                                  <child>
-                                  <placeholder/>
+                                  <object class="GtkCheckButton" 
id="launch-security">
+                                    <property name="label" 
translatable="yes">Enable launch security</property>
+                                    <property 
name="visible">True</property>
+                                    <property 
name="can-focus">True</property>
+                                    <property 
name="receives-default">False</property>
+                                    <property 
name="halign">start</property>
+                                    <property 
name="use-underline">True</property>
+                                    <property 
name="draw-indicator">True</property>
+                                    <signal name="toggled" 
handler="on_mem_launch_security_toggled" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property 
name="left-attach">1</property>
+                                    <property 
name="top-attach">4</property>
+                                  </packing>
                                  </child>
                                </object>
                                <packing>
diff --git a/virtManager/details/details.py b/virtManager/details/details.py
index 24810f0f..c22a10fb 100644
--- a/virtManager/details/details.py
+++ b/virtManager/details/details.py
@@ -47,6 +47,7 @@ from ..delete import vmmDeleteStorage

   EDIT_MEM,
   EDIT_MEM_SHARED,
+ EDIT_MEM_SEV,

   EDIT_AUTOSTART,
   EDIT_BOOTORDER,
@@ -84,7 +85,7 @@ from ..delete import vmmDeleteStorage

   EDIT_FS,

- EDIT_HOSTDEV_ROMBAR) = range(1, 38)
+ EDIT_HOSTDEV_ROMBAR) = range(1, 39)


  # Columns in hw list model
@@ -437,6 +438,7 @@ class vmmDetails(vmmGObjectUI):
              "on_mem_maxmem_changed": _e(EDIT_MEM),
              "on_mem_memory_changed": self._curmem_changed_cb,
              "on_mem_shared_access_toggled": _e(EDIT_MEM_SHARED),
+            "on_mem_launch_security_toggled": _e(EDIT_MEM_SEV),

              "on_boot_list_changed": self._boot_list_changed_cb,
              "on_boot_moveup_clicked": self._boot_moveup_clicked_cb,
@@ -1467,6 +1469,9 @@ class vmmDetails(vmmGObjectUI):
          if self._edited(EDIT_MEM_SHARED):
              kwargs["mem_shared"] = 
self.widget("shared-memory").get_active()

+        if self._edited(EDIT_MEM_SEV):
+            kwargs["sevmem"] = self.widget("launch-security").get_active()
+
          return self._change_config(
                  self.vm.define_memory, kwargs,
                  hotplug_args=hotplug_args)
@@ -1972,6 +1977,14 @@ class vmmDetails(vmmGObjectUI):
          curmem.set_value(int(round(vm_cur_mem)))
          maxmem.set_value(int(round(vm_max_mem)))

+        domcaps = self.vm.get_domain_capabilities()
+        show_sev = domcaps.supports_sev_launch_security()
+        self.widget("launch-security").set_sensitive(show_sev)
+        if self.vm.get_launch_security_type():
+            self.widget("launch-security").set_active(True)
+        else:
+            self.widget("launch-security").set_active(False)
+
          shared_mem, shared_mem_err = self.vm.has_shared_mem()
          self.widget("shared-memory").set_active(shared_mem)
          self.widget("shared-memory").set_sensitive(not 
bool(shared_mem_err))
diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py
index 70e4e49f..feb43bd2 100644
--- a/virtManager/object/domain.py
+++ b/virtManager/object/domain.py
@@ -688,7 +688,7 @@ class vmmDomain(vmmLibvirtObject):
              guest.memoryBacking.access_mode = access_mode

      def define_memory(self, memory=_SENTINEL, maxmem=_SENTINEL,
-            mem_shared=_SENTINEL):
+            mem_shared=_SENTINEL, sevmem=_SENTINEL):
          guest = self._make_xmlobj_to_define()

          if memory != _SENTINEL:
@@ -697,6 +697,15 @@ class vmmDomain(vmmLibvirtObject):
              guest.memory = int(maxmem)
          if mem_shared != _SENTINEL:
              self._edit_shared_mem(guest, mem_shared)
+        if sevmem != _SENTINEL:
+            if sevmem is True:
+                guest.launchSecurity.type = "sev"
+                guest.launchSecurity.set_defaults(guest)
+                guest.memoryBacking.set_locked(True)
+            else:
+                guest.launchSecurity.type = None
+                guest.launchSecurity.policy = None
+                guest.memoryBacking.set_locked(False)

          self._redefine_xmlobj(guest)

@@ -1310,6 +1319,9 @@ class vmmDomain(vmmLibvirtObject):
      def get_description(self):
          return self.get_xmlobj().description

+    def get_launch_security_type(self):
+        return self.get_xmlobj().launchSecurity.type
+
      def get_boot_order(self):
          legacy = not self.can_use_device_boot_order()
          return self.xmlobj.get_boot_order(legacy=legacy)
diff --git a/virtinst/domain/launch_security.py 
b/virtinst/domain/launch_security.py
index 7af71811..f4a4a4b8 100644
--- a/virtinst/domain/launch_security.py
+++ b/virtinst/domain/launch_security.py
@@ -19,16 +19,23 @@ class DomainLaunchSecurity(XMLBuilder):
      kernelHashes = XMLProperty("./@kernelHashes", is_yesno=True)

      def _set_defaults_sev(self, guest):
-        if not guest.os.is_q35() or not guest.is_uefi():
-            raise RuntimeError(_("SEV launch security requires a Q35 
UEFI machine"))
+        if not guest.os.is_q35():
+            raise RuntimeError(_("SEV launch security requires a Q35 
machine"))
+        # Libvirt will select the appropriate firmware file based on 
the policy
+        # defined below and if efi is enabled.
+        if not guest.is_uefi():
+            guest.os.firmware = 'efi'

-        # 'policy' is a mandatory 4-byte argument for the SEV firmware,
-        # if missing, let's use 0x03 which, according to the table at
-        # https://libvirt.org/formatdomain.html#launchSecurity:
-        # (bit 0) - disables the debugging mode
-        # (bit 1) - disables encryption key sharing across multiple guests
+        # The 'policy' is a mandatory 4-byte argument for the SEV firmware.
+        # If missing, we use 0x03 for the original SEV implementation and
+        # 0x07 for SEV-ES.
+        # Reference: https://libvirt.org/formatdomain.html#launchSecurity
          if self.policy is None:
-            self.policy = "0x03"
+            domcaps = guest.lookup_domcaps()
+            if domcaps.supports_sev_launch_security(check_es=True):
+                self.policy = "0x07"
+            else:
+                self.policy = "0x03"

      def set_defaults(self, guest):
          if self.type == "sev":
diff --git a/virtinst/domain/memorybacking.py 
b/virtinst/domain/memorybacking.py
index c883c57d..4ddd3865 100644
--- a/virtinst/domain/memorybacking.py
+++ b/virtinst/domain/memorybacking.py
@@ -27,6 +27,9 @@ class DomainMemoryBacking(XMLBuilder):
      XML_NAME = "memoryBacking"
      _XML_PROP_ORDER = ["hugepages", "nosharepages", "locked", "pages"]

+    def set_locked(self, value):
+        self.locked = value
+
      hugepages = XMLProperty("./hugepages", is_bool=True)
      nosharepages = XMLProperty("./nosharepages", is_bool=True)
      locked = XMLProperty("./locked", is_bool=True)
diff --git a/virtinst/domcapabilities.py b/virtinst/domcapabilities.py
index 3ebc409d..4d79c6d1 100644
--- a/virtinst/domcapabilities.py
+++ b/virtinst/domcapabilities.py
@@ -93,6 +93,10 @@ def _make_capsblock(xml_root_name):
  class _SEV(XMLBuilder):
      XML_NAME = "sev"
      supported = XMLProperty("./@supported", is_yesno=True)
+    cbitpos = XMLProperty("./cbitpos")
+    reducedPhysBits = XMLProperty("./reducedPhysBits")
+    maxGuests = XMLProperty("./maxGuests")
+    maxESGuests = XMLProperty("./maxESGuests")


  #############################
@@ -390,12 +394,14 @@ class DomainCapabilities(XMLBuilder):
      # Misc support methods #
      ########################

-    def supports_sev_launch_security(self):
+    def supports_sev_launch_security(self, check_es=False):
          """
          Returns False if either libvirt doesn't advertise support for 
SEV at
          all (< libvirt-4.5.0) or if it explicitly advertises it as 
unsupported
          on the platform
          """
+        if check_es:
+            return bool(self.features.sev.supported and 
self.features.sev.maxESGuests)
          return bool(self.features.sev.supported)

      def supports_video_bochs(self):
-- 
2.31.1




More information about the virt-tools-list mailing list