Blob Blame History Raw
From 43382d91d15bf35798590ce786c2ae6a0d0bae5c Mon Sep 17 00:00:00 2001
Message-Id: <43382d91d15bf35798590ce786c2ae6a0d0bae5c@dist-git>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Fri, 5 Aug 2016 14:35:27 +0200
Subject: [PATCH] qemu: Enable secure boot

https://bugzilla.redhat.com/show_bug.cgi?id=1304483

In qemu, enabling this feature boils down to adding the following
onto the command line:

  -global driver=cfi.pflash01,property=secure,value=on

However, there are some constraints resulting from the
implementation. For instance, System Management Mode (SMM) is
required to be enabled, the machine type must be q35-2.4 or
later, and the guest should be x86_64. While technically it is
possible to have 32 bit guests with secure boot, some non-trivial
CPU flags tuning is required (for instance lm and nx flags must
be prohibited). Given complexity of our CPU driver, this is not
trivial. Therefore I've chosen to forbid 32 bit guests for now.
If there's ever need, we can refine the check later.

Also, for the RHEL-7.3 I had to adjust the machine-smm-opt test.
In the upstream we already retired QEMU_CAPS_SMP_TOPOLOGY
capability, but not in RHEL yet.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 9c1524a01c357ea235f90c345c3b6a2682ec05f2)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 src/qemu/qemu_command.c                            |  7 ++++++
 src/qemu/qemu_domain.c                             | 27 ++++++++++++++++++++
 .../qemuxml2argv-bios-nvram-secure.args            | 29 ++++++++++++++++++++++
 tests/qemuxml2argvtest.c                           |  8 ++++++
 4 files changed, 71 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 773f5f3..6be16cc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8949,6 +8949,13 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
             goto cleanup;
         }
 
+        if (loader->secure == VIR_TRISTATE_BOOL_YES) {
+            virCommandAddArgList(cmd,
+                                 "-global",
+                                 "driver=cfi.pflash01,property=secure,value=on",
+                                 NULL);
+        }
+
         virBufferAsprintf(&buf,
                           "file=%s,if=pflash,format=raw,unit=%d",
                           loader->path, unit);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a6a0121..cc726dc 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2228,6 +2228,33 @@ qemuDomainDefValidate(const virDomainDef *def,
         return -1;
     }
 
+    if (def->os.loader &&
+        def->os.loader->secure == VIR_TRISTATE_BOOL_YES) {
+        /* These are the QEMU implementation limitations. But we
+         * have to live with them for now. */
+
+        if (!qemuDomainMachineIsQ35(def)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Secure boot is supported with q35 machine types only"));
+            return -1;
+        }
+
+        /* Now, technically it is possible to have secure boot on
+         * 32bits too, but that would require some -cpu xxx magic
+         * too. Not worth it unless we are explicitly asked. */
+        if (def->os.arch != VIR_ARCH_X86_64) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Secure boot is supported for x86_64 architecture only"));
+            return -1;
+        }
+
+        if (def->features[VIR_DOMAIN_FEATURE_SMM] != VIR_TRISTATE_SWITCH_ON) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Secure boot requires SMM feature enabled"));
+            return -1;
+        }
+    }
+
     return 0;
 }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args
new file mode 100644
index 0000000..c014254
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args
@@ -0,0 +1,29 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name test-bios \
+-S \
+-machine pc-q35-2.5,accel=tcg,smm=on \
+-global driver=cfi.pflash01,property=secure,value=on \
+-drive file=/usr/share/OVMF/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,\
+readonly=on \
+-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
+-m 1024 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid 362d1fc1-df7d-193e-5c18-49a71bd1da66 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/lib/domain--1-test-bios/monitor.sock,server,nowait \
+-boot c \
+-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \
+-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \
+-device virtio-scsi-pci,id=scsi0,bus=pci.2,addr=0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-scsi0-0-0-0 \
+-device scsi-disk,bus=scsi0.0,channel=0,scsi-id=0,lun=0,\
+drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
+-serial pty \
+-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x2
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 5c26812..95474e8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -685,6 +685,14 @@ mymain(void)
 
     DO_TEST("bios", QEMU_CAPS_SGA);
     DO_TEST("bios-nvram", NONE);
+    DO_TEST("bios-nvram-secure",
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_ICH9_AHCI,
+            QEMU_CAPS_MACHINE_OPT,
+            QEMU_CAPS_MACHINE_SMM_OPT,
+            QEMU_CAPS_SMP_TOPOLOGY,
+            QEMU_CAPS_VIRTIO_SCSI);
     DO_TEST("clock-utc", QEMU_CAPS_NODEFCONFIG);
     DO_TEST("clock-localtime", NONE);
     DO_TEST("clock-localtime-basis-localtime", QEMU_CAPS_RTC);
-- 
2.9.2