Set the kernel-hashes property on the sev-guest object if the config
asked for it explicitly. While QEMU machine types currently default to
having this setting off, it is not guaranteed to remain this way.
We can't assume that the QEMU capabilities were generated on an AMD host
with SEV, so we must force set the QEMU_CAPS_SEV_GUEST. This also means
that the 'sev' info in the qemuCaps struct might be NULL, but this is
harmless from POV of testing the CLI generator.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/qemu/qemu_capabilities.c | 5 +++
src/qemu/qemu_command.c | 1 +
src/qemu/qemu_validate.c | 7 ++++
...nch-security-sev-direct.x86_64-latest.args | 40 +++++++++++++++++++
.../launch-security-sev-direct.xml | 39 ++++++++++++++++++
tests/qemuxml2argvtest.c | 5 +++
tests/testutilsqemu.c | 15 ++++---
7 files changed, 107 insertions(+), 5 deletions(-)
create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/launch-security-sev-direct.xml
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c1b06998af..4f63322a9e 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -1892,6 +1892,11 @@ virQEMUCapsSEVInfoCopy(virSEVCapability **dst,
{
g_autoptr(virSEVCapability) tmp = NULL;
+ if (!src) {
+ *dst = NULL;
+ return 0;
+ }
+
tmp = g_new0(virSEVCapability, 1);
tmp->pdh = g_strdup(src->pdh);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6d00105b24..4d5f7934cb 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9928,6 +9928,7 @@ qemuBuildSEVCommandLine(virDomainObj *vm, virCommand *cmd,
"u:policy", sev->policy,
"S:dh-cert-file", dhpath,
"S:session-file", sessionpath,
+ "T:kernel-hashes", sev->kernel_hashes,
NULL) < 0)
return -1;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index f9a195e991..c1924eb2ad 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1217,6 +1217,13 @@ qemuValidateDomainDef(const virDomainDef *def,
"this QEMU binary"));
return -1;
}
+
+ if (def->sec->data.sev.kernel_hashes != VIR_TRISTATE_BOOL_ABSENT
&&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST_KERNEL_HASHES)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("SEV measured direct kernel boot is not supported
with this QEMU binary"));
+ return -1;
+ }
break;
case VIR_DOMAIN_LAUNCH_SECURITY_PV:
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_CONFIDENTAL_GUEST_SUPPORT)
||
diff --git a/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-latest.args
b/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-latest.args
new file mode 100644
index 0000000000..dac312e301
--- /dev/null
+++ b/tests/qemuxml2argvdata/launch-security-sev-direct.x86_64-latest.args
@@ -0,0 +1,40 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}'
\
+-machine
pc,usb=off,dump-guest-core=off,confidential-guest-support=lsec0,memory-backend=pc.ram \
+-accel kvm \
+-cpu qemu64 \
+-m 214 \
+-object
'{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}'
\
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-kernel /vmlinuz \
+-initrd /initrd \
+-append runme \
+-device
'{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}'
\
+-blockdev
'{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}'
\
+-blockdev
'{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}'
\
+-device
'{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}'
\
+-audiodev
'{"id":"audio1","driver":"none"}' \
+-object
'{"qom-type":"sev-guest","id":"lsec0","cbitpos":47,"reduced-phys-bits":1,"policy":1,"dh-cert-file":"/tmp/lib/domain--1-QEMUGuest1/dh_cert.base64","session-file":"/tmp/lib/domain--1-QEMUGuest1/session.base64","kernel-hashes":true}'
\
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/launch-security-sev-direct.xml
b/tests/qemuxml2argvdata/launch-security-sev-direct.xml
new file mode 100644
index 0000000000..80ce6412dd
--- /dev/null
+++ b/tests/qemuxml2argvdata/launch-security-sev-direct.xml
@@ -0,0 +1,39 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <kernel>/vmlinuz</kernel>
+ <initrd>/initrd</initrd>
+ <cmdline>runme</cmdline>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <memballoon model='none'/>
+ </devices>
+ <launchSecurity type='sev' kernelHashes='yes'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x0001</policy>
+ <dhCert>AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA</dhCert>
+ <session>IHAVENOIDEABUTJUSTPROVIDINGASTRING</session>
+ </launchSecurity>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 0b88b580c5..6c67b36d5c 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3425,6 +3425,11 @@ mymain(void)
DO_TEST_CAPS_VER("launch-security-sev", "2.12.0");
DO_TEST_CAPS_VER("launch-security-sev", "6.0.0");
DO_TEST_CAPS_VER("launch-security-sev-missing-platform-info",
"2.12.0");
+ DO_TEST_CAPS_ARCH_LATEST_FULL("launch-security-sev-direct",
+ "x86_64",
+ ARG_QEMU_CAPS,
+ QEMU_CAPS_SEV_GUEST,
+ QEMU_CAPS_LAST);
DO_TEST_CAPS_ARCH_LATEST("launch-security-s390-pv", "s390x");
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index 7b19575d8b..7fdb82daec 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -772,11 +772,6 @@ testQemuInfoInitArgs(struct testQemuInfo *info)
bool stripmachinealiases = false;
virQEMUCaps *cachedcaps = NULL;
- if (info->args.fakeCapsUsed) {
- fprintf(stderr, "ARG_QEMU_CAPS can not be combined with ARG_CAPS_ARCH or
ARG_CAPS_VER\n");
- return -1;
- }
-
info->arch = virArchFromString(info->args.capsarch);
if (STREQ(info->args.capsver, "latest")) {
@@ -805,6 +800,16 @@ testQemuInfoInitArgs(struct testQemuInfo *info)
if (!(info->qemuCaps = virQEMUCapsNewCopy(cachedcaps)))
return -1;
+ if (info->args.fakeCapsUsed) {
+ size_t i;
+ for (i = 0; i < QEMU_CAPS_LAST; i++) {
+ if (virQEMUCapsGet(info->args.fakeCaps, i)) {
+ virQEMUCapsSet(info->qemuCaps, i);
+ }
+ }
+ }
+
+
if (stripmachinealiases)
virQEMUCapsStripMachineAliases(info->qemuCaps);
--
2.33.1