6ae9ed
From 43382d91d15bf35798590ce786c2ae6a0d0bae5c Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <43382d91d15bf35798590ce786c2ae6a0d0bae5c@dist-git>
6ae9ed
From: Michal Privoznik <mprivozn@redhat.com>
6ae9ed
Date: Fri, 5 Aug 2016 14:35:27 +0200
6ae9ed
Subject: [PATCH] qemu: Enable secure boot
6ae9ed
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1304483
6ae9ed
6ae9ed
In qemu, enabling this feature boils down to adding the following
6ae9ed
onto the command line:
6ae9ed
6ae9ed
  -global driver=cfi.pflash01,property=secure,value=on
6ae9ed
6ae9ed
However, there are some constraints resulting from the
6ae9ed
implementation. For instance, System Management Mode (SMM) is
6ae9ed
required to be enabled, the machine type must be q35-2.4 or
6ae9ed
later, and the guest should be x86_64. While technically it is
6ae9ed
possible to have 32 bit guests with secure boot, some non-trivial
6ae9ed
CPU flags tuning is required (for instance lm and nx flags must
6ae9ed
be prohibited). Given complexity of our CPU driver, this is not
6ae9ed
trivial. Therefore I've chosen to forbid 32 bit guests for now.
6ae9ed
If there's ever need, we can refine the check later.
6ae9ed
6ae9ed
Also, for the RHEL-7.3 I had to adjust the machine-smm-opt test.
6ae9ed
In the upstream we already retired QEMU_CAPS_SMP_TOPOLOGY
6ae9ed
capability, but not in RHEL yet.
6ae9ed
6ae9ed
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
6ae9ed
(cherry picked from commit 9c1524a01c357ea235f90c345c3b6a2682ec05f2)
6ae9ed
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
6ae9ed
---
6ae9ed
 src/qemu/qemu_command.c                            |  7 ++++++
6ae9ed
 src/qemu/qemu_domain.c                             | 27 ++++++++++++++++++++
6ae9ed
 .../qemuxml2argv-bios-nvram-secure.args            | 29 ++++++++++++++++++++++
6ae9ed
 tests/qemuxml2argvtest.c                           |  8 ++++++
6ae9ed
 4 files changed, 71 insertions(+)
6ae9ed
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args
6ae9ed
6ae9ed
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
6ae9ed
index 773f5f3..6be16cc 100644
6ae9ed
--- a/src/qemu/qemu_command.c
6ae9ed
+++ b/src/qemu/qemu_command.c
6ae9ed
@@ -8949,6 +8949,13 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
6ae9ed
             goto cleanup;
6ae9ed
         }
6ae9ed
 
6ae9ed
+        if (loader->secure == VIR_TRISTATE_BOOL_YES) {
6ae9ed
+            virCommandAddArgList(cmd,
6ae9ed
+                                 "-global",
6ae9ed
+                                 "driver=cfi.pflash01,property=secure,value=on",
6ae9ed
+                                 NULL);
6ae9ed
+        }
6ae9ed
+
6ae9ed
         virBufferAsprintf(&buf,
6ae9ed
                           "file=%s,if=pflash,format=raw,unit=%d",
6ae9ed
                           loader->path, unit);
6ae9ed
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
6ae9ed
index a6a0121..cc726dc 100644
6ae9ed
--- a/src/qemu/qemu_domain.c
6ae9ed
+++ b/src/qemu/qemu_domain.c
6ae9ed
@@ -2228,6 +2228,33 @@ qemuDomainDefValidate(const virDomainDef *def,
6ae9ed
         return -1;
6ae9ed
     }
6ae9ed
 
6ae9ed
+    if (def->os.loader &&
6ae9ed
+        def->os.loader->secure == VIR_TRISTATE_BOOL_YES) {
6ae9ed
+        /* These are the QEMU implementation limitations. But we
6ae9ed
+         * have to live with them for now. */
6ae9ed
+
6ae9ed
+        if (!qemuDomainMachineIsQ35(def)) {
6ae9ed
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6ae9ed
+                           _("Secure boot is supported with q35 machine types only"));
6ae9ed
+            return -1;
6ae9ed
+        }
6ae9ed
+
6ae9ed
+        /* Now, technically it is possible to have secure boot on
6ae9ed
+         * 32bits too, but that would require some -cpu xxx magic
6ae9ed
+         * too. Not worth it unless we are explicitly asked. */
6ae9ed
+        if (def->os.arch != VIR_ARCH_X86_64) {
6ae9ed
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6ae9ed
+                           _("Secure boot is supported for x86_64 architecture only"));
6ae9ed
+            return -1;
6ae9ed
+        }
6ae9ed
+
6ae9ed
+        if (def->features[VIR_DOMAIN_FEATURE_SMM] != VIR_TRISTATE_SWITCH_ON) {
6ae9ed
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6ae9ed
+                           _("Secure boot requires SMM feature enabled"));
6ae9ed
+            return -1;
6ae9ed
+        }
6ae9ed
+    }
6ae9ed
+
6ae9ed
     return 0;
6ae9ed
 }
6ae9ed
 
6ae9ed
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args
6ae9ed
new file mode 100644
6ae9ed
index 0000000..c014254
6ae9ed
--- /dev/null
6ae9ed
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram-secure.args
6ae9ed
@@ -0,0 +1,29 @@
6ae9ed
+LC_ALL=C \
6ae9ed
+PATH=/bin \
6ae9ed
+HOME=/home/test \
6ae9ed
+USER=test \
6ae9ed
+LOGNAME=test \
6ae9ed
+QEMU_AUDIO_DRV=none \
6ae9ed
+/usr/bin/qemu \
6ae9ed
+-name test-bios \
6ae9ed
+-S \
6ae9ed
+-machine pc-q35-2.5,accel=tcg,smm=on \
6ae9ed
+-global driver=cfi.pflash01,property=secure,value=on \
6ae9ed
+-drive file=/usr/share/OVMF/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,\
6ae9ed
+readonly=on \
6ae9ed
+-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
6ae9ed
+-m 1024 \
6ae9ed
+-smp 1,sockets=1,cores=1,threads=1 \
6ae9ed
+-uuid 362d1fc1-df7d-193e-5c18-49a71bd1da66 \
6ae9ed
+-nographic \
6ae9ed
+-nodefaults \
6ae9ed
+-monitor unix:/tmp/lib/domain--1-test-bios/monitor.sock,server,nowait \
6ae9ed
+-boot c \
6ae9ed
+-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \
6ae9ed
+-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \
6ae9ed
+-device virtio-scsi-pci,id=scsi0,bus=pci.2,addr=0x1 \
6ae9ed
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-scsi0-0-0-0 \
6ae9ed
+-device scsi-disk,bus=scsi0.0,channel=0,scsi-id=0,lun=0,\
6ae9ed
+drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
6ae9ed
+-serial pty \
6ae9ed
+-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x2
6ae9ed
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
6ae9ed
index 5c26812..95474e8 100644
6ae9ed
--- a/tests/qemuxml2argvtest.c
6ae9ed
+++ b/tests/qemuxml2argvtest.c
6ae9ed
@@ -685,6 +685,14 @@ mymain(void)
6ae9ed
 
6ae9ed
     DO_TEST("bios", QEMU_CAPS_SGA);
6ae9ed
     DO_TEST("bios-nvram", NONE);
6ae9ed
+    DO_TEST("bios-nvram-secure",
6ae9ed
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
6ae9ed
+            QEMU_CAPS_DEVICE_PCI_BRIDGE,
6ae9ed
+            QEMU_CAPS_ICH9_AHCI,
6ae9ed
+            QEMU_CAPS_MACHINE_OPT,
6ae9ed
+            QEMU_CAPS_MACHINE_SMM_OPT,
6ae9ed
+            QEMU_CAPS_SMP_TOPOLOGY,
6ae9ed
+            QEMU_CAPS_VIRTIO_SCSI);
6ae9ed
     DO_TEST("clock-utc", QEMU_CAPS_NODEFCONFIG);
6ae9ed
     DO_TEST("clock-localtime", NONE);
6ae9ed
     DO_TEST("clock-localtime-basis-localtime", QEMU_CAPS_RTC);
6ae9ed
-- 
6ae9ed
2.9.2
6ae9ed