Blame SOURCES/virt-manager-virt-manager-add-new-checkbox-to-control-CPU-security-features.patch

3d61c0
From 50eaeeb15e51030ac9548a90e7388868a645ecca Mon Sep 17 00:00:00 2001
3d61c0
Message-Id: <50eaeeb15e51030ac9548a90e7388868a645ecca@dist-git>
3d61c0
From: Pavel Hrdina <phrdina@redhat.com>
3d61c0
Date: Wed, 3 Apr 2019 15:23:20 +0200
3d61c0
Subject: [PATCH] virt-manager: add new checkbox to control CPU security
3d61c0
 features
3d61c0
MIME-Version: 1.0
3d61c0
Content-Type: text/plain; charset=UTF-8
3d61c0
Content-Transfer-Encoding: 8bit
3d61c0
3d61c0
By default we copy CPU security features to the guest if specific CPU
3d61c0
model is selected.  However, this may break migration and will affect
3d61c0
performance of the guest.  This adds an option to disable this default
3d61c0
behavior.
3d61c0
3d61c0
The checkbox is clickable only on x86 and only on host where we can
3d61c0
detect any CPU security features, otherwise a tooltip is set to notify
3d61c0
users that there is nothing to copy.
3d61c0
3d61c0
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
3d61c0
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
3d61c0
(cherry picked from commit 8720637cff7b0766d9e27a60b0f81740176d70c8)
3d61c0
3d61c0
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1582667
3d61c0
3d61c0
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
3d61c0
Reviewed-by: Cole Robinson <crobinso@redhat.com>
3d61c0
---
3d61c0
 ui/details.ui          | 15 +++++++++++++++
3d61c0
 virtManager/details.py | 21 +++++++++++++++++++++
3d61c0
 virtManager/domain.py  |  5 +++--
3d61c0
 virtinst/cpu.py        | 30 ++++++++++++++++++++++++++++++
3d61c0
 4 files changed, 69 insertions(+), 2 deletions(-)
3d61c0
3d61c0
diff --git a/ui/details.ui b/ui/details.ui
3d61c0
index e0689f4d..6fe5e18a 100644
3d61c0
--- a/ui/details.ui
3d61c0
+++ b/ui/details.ui
3d61c0
@@ -2213,6 +2213,21 @@
3d61c0
                                             <property name="top_attach">1</property>
3d61c0
                                           </packing>
3d61c0
                                         </child>
3d61c0
+                                        <child>
3d61c0
+                                          <object class="GtkCheckButton" id="cpu-secure">
3d61c0
+                                            <property name="label" translatable="yes">Enable available CPU security flaw mitigations</property>
3d61c0
+                                            <property name="visible">True</property>
3d61c0
+                                            <property name="can_focus">True</property>
3d61c0
+                                            <property name="receives_default">False</property>
3d61c0
+                                            <property name="draw_indicator">True</property>
3d61c0
+                                            <signal name="toggled" handler="on_cpu_secure_toggled" swapped="no"/>
3d61c0
+                                          </object>
3d61c0
+                                          <packing>
3d61c0
+                                            <property name="left_attach">0</property>
3d61c0
+                                            <property name="top_attach">2</property>
3d61c0
+                                            <property name="width">2</property>
3d61c0
+                                          </packing>
3d61c0
+                                        </child>
3d61c0
                                       </object>
3d61c0
                                     </child>
3d61c0
                                   </object>
3d61c0
diff --git a/virtManager/details.py b/virtManager/details.py
3d61c0
index 65fea500..e5028b25 100644
3d61c0
--- a/virtManager/details.py
3d61c0
+++ b/virtManager/details.py
3d61c0
@@ -507,6 +507,7 @@ class vmmDetails(vmmGObjectUI):
3d61c0
             "on_cpu_maxvcpus_changed": self.config_maxvcpus_changed,
3d61c0
             "on_cpu_model_changed": lambda *x: self.config_cpu_model_changed(x),
3d61c0
             "on_cpu_copy_host_clicked": self.on_cpu_copy_host_clicked,
3d61c0
+            "on_cpu_secure_toggled": self.on_cpu_secure_toggled,
3d61c0
             "on_cpu_cores_changed": self.config_cpu_topology_changed,
3d61c0
             "on_cpu_sockets_changed": self.config_cpu_topology_changed,
3d61c0
             "on_cpu_threads_changed": self.config_cpu_topology_changed,
3d61c0
@@ -1700,6 +1701,11 @@ class vmmDetails(vmmGObjectUI):
3d61c0
     def on_cpu_copy_host_clicked(self, src):
3d61c0
         uiutil.set_grid_row_visible(
3d61c0
             self.widget("cpu-model"), not src.get_active())
3d61c0
+        uiutil.set_grid_row_visible(
3d61c0
+            self.widget("cpu-secure"), not src.get_active())
3d61c0
+        self.enable_apply(EDIT_CPU)
3d61c0
+
3d61c0
+    def on_cpu_secure_toggled(self, ignore):
3d61c0
         self.enable_apply(EDIT_CPU)
3d61c0
 
3d61c0
     def config_cpu_model_changed(self, ignore):
3d61c0
@@ -1999,6 +2005,7 @@ class vmmDetails(vmmGObjectUI):
3d61c0
 
3d61c0
         if self.edited(EDIT_CPU):
3d61c0
             kwargs["model"] = self.get_config_cpu_model()
3d61c0
+            kwargs["secure"] = self.widget("cpu-secure").get_active()
3d61c0
 
3d61c0
         if self.edited(EDIT_TOPOLOGY):
3d61c0
             do_top = self.widget("cpu-topology-enable").get_active()
3d61c0
@@ -2529,6 +2536,11 @@ class vmmDetails(vmmGObjectUI):
3d61c0
         n1, n2 = self.vm.network_traffic_vectors()
3d61c0
         self.network_traffic_graph.set_property("data_array", n1 + n2)
3d61c0
 
3d61c0
+    def _cpu_secure_is_available(self):
3d61c0
+        domcaps = self.vm.get_domain_capabilities()
3d61c0
+        features = domcaps.get_cpu_security_features()
3d61c0
+        return self.vm.get_xmlobj().os.is_x86() and len(features) > 0
3d61c0
+
3d61c0
     def refresh_config_cpu(self):
3d61c0
         # Set topology first, because it impacts maxvcpus values
3d61c0
         cpu = self.vm.get_cpu_config()
3d61c0
@@ -2582,6 +2594,15 @@ class vmmDetails(vmmGObjectUI):
3d61c0
         self.widget("cpu-copy-host").set_active(bool(is_host))
3d61c0
         self.on_cpu_copy_host_clicked(self.widget("cpu-copy-host"))
3d61c0
 
3d61c0
+        if not self._cpu_secure_is_available():
3d61c0
+            self.widget("cpu-secure").set_sensitive(False)
3d61c0
+            self.widget("cpu-secure").set_tooltip_text(
3d61c0
+                    "No security features to copy, the host is missing "
3d61c0
+                    "security patches or the host CPU is not vulnerable.")
3d61c0
+
3d61c0
+        cpu.check_security_features(self.vm.get_xmlobj())
3d61c0
+        self.widget("cpu-secure").set_active(cpu.secure)
3d61c0
+
3d61c0
     def refresh_config_memory(self):
3d61c0
         host_mem_widget = self.widget("state-host-memory")
3d61c0
         host_mem = self.vm.conn.host_memory_size() // 1024
3d61c0
diff --git a/virtManager/domain.py b/virtManager/domain.py
3d61c0
index 7c1f511d..c423a177 100644
3d61c0
--- a/virtManager/domain.py
3d61c0
+++ b/virtManager/domain.py
3d61c0
@@ -647,7 +647,7 @@ class vmmDomain(vmmLibvirtObject):
3d61c0
         self._redefine_xmlobj(xmlobj)
3d61c0
 
3d61c0
     def define_cpu(self, vcpus=_SENTINEL, maxvcpus=_SENTINEL,
3d61c0
-            model=_SENTINEL, sockets=_SENTINEL,
3d61c0
+            model=_SENTINEL, secure=_SENTINEL, sockets=_SENTINEL,
3d61c0
             cores=_SENTINEL, threads=_SENTINEL):
3d61c0
         guest = self._make_xmlobj_to_define()
3d61c0
 
3d61c0
@@ -661,7 +661,8 @@ class vmmDomain(vmmLibvirtObject):
3d61c0
             guest.cpu.cores = cores
3d61c0
             guest.cpu.threads = threads
3d61c0
 
3d61c0
-        if model != _SENTINEL:
3d61c0
+        if secure != _SENTINEL or model != _SENTINEL:
3d61c0
+            guest.cpu.secure = secure
3d61c0
             if model in guest.cpu.SPECIAL_MODES:
3d61c0
                 guest.cpu.set_special_mode(guest, model)
3d61c0
             else:
3d61c0
diff --git a/virtinst/cpu.py b/virtinst/cpu.py
3d61c0
index 4776f90e..c76f06e8 100644
3d61c0
--- a/virtinst/cpu.py
3d61c0
+++ b/virtinst/cpu.py
3d61c0
@@ -145,6 +145,36 @@ class CPU(XMLBuilder):
3d61c0
             if not exists:
3d61c0
                 self.add_feature(feature)
3d61c0
 
3d61c0
+    def check_security_features(self, guest):
3d61c0
+        """
3d61c0
+        Since 'secure' property is not exported into the domain XML
3d61c0
+        we might need to refresh its state.
3d61c0
+        """
3d61c0
+        domcaps = guest.lookup_domcaps()
3d61c0
+        features = domcaps.get_cpu_security_features()
3d61c0
+
3d61c0
+        if len(features) == 0:
3d61c0
+            self.secure = False
3d61c0
+            return
3d61c0
+
3d61c0
+        for feature in features:
3d61c0
+            exists = False
3d61c0
+            for f in self.features:
3d61c0
+                if f.name == feature and f.policy == "require":
3d61c0
+                    exists = True
3d61c0
+                    break
3d61c0
+            if not exists:
3d61c0
+                self.secure = False
3d61c0
+                return
3d61c0
+
3d61c0
+    def _remove_security_features(self, guest):
3d61c0
+        domcaps = guest.lookup_domcaps()
3d61c0
+        for feature in domcaps.get_cpu_security_features():
3d61c0
+            for f in self.features:
3d61c0
+                if f.name == feature and f.policy == "require":
3d61c0
+                    self.remove_child(f)
3d61c0
+                    break
3d61c0
+
3d61c0
     def set_model(self, guest, val):
3d61c0
         logging.debug("setting cpu model %s", val)
3d61c0
         if val:
3d61c0
-- 
3d61c0
2.20.1
3d61c0