domain: launch_security: simplify defaults and validation

* libvirt fills in cbitpos and reducedPhysBits for us
* libvirt errors if type is missing
* libvirt errors if host/qemu doesn't support sev

So drop it all. This simplifies testing because we don't need
sev domcaps in place just to generate the XML

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2022-02-28 08:36:52 -05:00
parent 1aaa28e26a
commit e0c5d74e82
9 changed files with 20 additions and 193 deletions

View File

@ -910,6 +910,13 @@
<driver aw_bits="48" intremap="off" caching_mode="on" eim="off" iotlb="off"/>
</iommu>
</devices>
<launchSecurity type="sev" kernelHashes="yes">
<cbitpos>47</cbitpos>
<reducedPhysBits>1</reducedPhysBits>
<policy>0x0001</policy>
<session>BASE64SESSION</session>
<dhCert>BASE64CERT</dhCert>
</launchSecurity>
<seclabel type="static" model="selinux" relabel="yes">
<label>system_u:object_r:svirt_image_t:s0:c100,c200</label>
<baselabel>baselabel</baselabel>

View File

@ -61,5 +61,8 @@
</video>
<memballoon model="none"/>
</devices>
<launchSecurity type="sev">
<policy>0x03</policy>
</launchSecurity>
<seclabel relabel="yes"/>
</domain>

View File

@ -1,81 +0,0 @@
<domain type="kvm">
<name>vm1</name>
<uuid>00000000-1111-2222-3333-444444444444</uuid>
<memory>65536</memory>
<currentMemory>65536</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch="x86_64" machine="q35">hvm</type>
<loader readonly="yes" type="pflash">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
<boot dev="hd"/>
</os>
<features>
<acpi/>
<apic/>
<vmport state="off"/>
</features>
<cpu mode="host-model"/>
<clock offset="utc">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
</clock>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type="usb" model="ich9-ehci1"/>
<controller type="usb" model="ich9-uhci1">
<master startport="0"/>
</controller>
<controller type="usb" model="ich9-uhci2">
<master startport="2"/>
</controller>
<controller type="usb" model="ich9-uhci3">
<master startport="4"/>
</controller>
<controller type="pci" model="pcie-root"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<interface type="bridge">
<source bridge="testsuitebr0"/>
<mac address="00:11:22:33:44:55"/>
<model type="e1000e"/>
</interface>
<console type="pty"/>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
</channel>
<input type="tablet" bus="usb"/>
<graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
<image compression="off"/>
</graphics>
<sound model="ich9"/>
<video>
<model type="qxl"/>
</video>
<redirdev bus="usb" type="spicevmc"/>
<redirdev bus="usb" type="spicevmc"/>
</devices>
<launchSecurity type="sev" kernelHashes="yes">
<cbitpos>47</cbitpos>
<reducedPhysBits>1</reducedPhysBits>
<policy>0x0001</policy>
<session>BASE64SESSION</session>
<dhCert>BASE64CERT</dhCert>
</launchSecurity>
</domain>

View File

@ -1,79 +0,0 @@
<domain type="kvm">
<name>vm1</name>
<uuid>00000000-1111-2222-3333-444444444444</uuid>
<memory>65536</memory>
<currentMemory>65536</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch="x86_64" machine="q35">hvm</type>
<loader readonly="yes" type="pflash">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
<boot dev="hd"/>
</os>
<features>
<acpi/>
<apic/>
<vmport state="off"/>
</features>
<cpu mode="host-model"/>
<clock offset="utc">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
</clock>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type="usb" model="ich9-ehci1"/>
<controller type="usb" model="ich9-uhci1">
<master startport="0"/>
</controller>
<controller type="usb" model="ich9-uhci2">
<master startport="2"/>
</controller>
<controller type="usb" model="ich9-uhci3">
<master startport="4"/>
</controller>
<controller type="pci" model="pcie-root"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<controller type="pci" model="pcie-root-port"/>
<interface type="bridge">
<source bridge="testsuitebr0"/>
<mac address="00:11:22:33:44:55"/>
<model type="e1000e"/>
</interface>
<console type="pty"/>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
</channel>
<input type="tablet" bus="usb"/>
<graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
<image compression="off"/>
</graphics>
<sound model="ich9"/>
<video>
<model type="qxl"/>
</video>
<redirdev bus="usb" type="spicevmc"/>
<redirdev bus="usb" type="spicevmc"/>
</devices>
<launchSecurity type="sev">
<cbitpos>47</cbitpos>
<reducedPhysBits>1</reducedPhysBits>
<policy>0x03</policy>
</launchSecurity>
</domain>

View File

@ -93,6 +93,10 @@ def testDomainCapabilitiesx86():
assert caps.supports_filesystem_virtiofs()
assert caps.supports_memorybacking_memfd()
xml = open(DATADIR + "/kvm-x86_64-domcaps-amd-sev.xml").read()
caps = DomainCapabilities(utils.URIs.open_testdriver_cached(), xml)
assert caps.supports_sev_launch_security()
def testDomainCapabilitiesAArch64():
xml = open(DATADIR + "/kvm-aarch64-domcaps.xml").read()

View File

@ -765,6 +765,9 @@ source.reservations.managed=no,source.reservations.source.type=unix,source.reser
--seclabel type=dynamic,label=012:345
--launchSecurity type=sev,reducedPhysBits=1,policy=0x0001,cbitpos=47,dhCert=BASE64CERT,session=BASE64SESSION,kernelHashes=yes
--qemu-commandline env=DISPLAY=:0.1
--qemu-commandline="-display gtk,gl=on"
--qemu-commandline="-device vfio-pci,addr=05.0,sysfsdev=/sys/class/mdev_bus/0000:00:02.0/f321853c-c584-4a6b-b99a-3eee22a3919c"
@ -796,6 +799,7 @@ c.add_compare(
"--sysinfo host " # special `--sysinfo host` handling
"--noapic --noacpi " # feature backcompat
"--boot uefi,cdrom,fd,hd,network,menu=on " # uefi for default devices, + old style bootorder
"--launchSecurity sev " # sev defaults
# Disabling all the default device setup
"""
@ -1098,6 +1102,7 @@ c.add_invalid("--disk none --location nfs:example.com/fake --nonetworks", grep="
c.add_invalid("--disk none --boot network --machine foobar", grep="domain type None with machine 'foobar'")
c.add_invalid("--nodisks --boot network --arch mips --virt-type kvm", grep="any virtualization options for architecture 'mips'")
c.add_invalid("--nodisks --boot network --paravirt --arch mips", grep=" 'xen' for architecture 'mips'")
c.add_invalid("--osinfo generic --launchSecurity sev --connect " + utils.URIs.kvm_amd_sev, grep="SEV launch security requires a Q35 UEFI machine")
@ -1171,13 +1176,6 @@ c.add_compare("--connect %(URI-KVM-AARCH64)s --osinfo fedora30 --arch aarch64 --
#################
c = vinst.add_category("kvm-x86_64-launch-security", "--disk none --noautoconsole --osinfo generic")
c.add_compare("--boot uefi --machine q35 --launchSecurity type=sev,reducedPhysBits=1,policy=0x0001,cbitpos=47,dhCert=BASE64CERT,session=BASE64SESSION,kernelHashes=yes --connect " + utils.URIs.kvm_amd_sev, "x86_64-launch-security-sev-full") # Full cmdline
c.add_compare("--boot uefi --machine q35 --launchSecurity sev --connect " + utils.URIs.kvm_amd_sev, "x86_64-launch-security-sev") # Fill in platform data from domcaps
c.add_valid("--boot uefi --machine q35 --launchSecurity sev,reducedPhysBits=1,cbitpos=47 --connect " + utils.URIs.kvm_amd_sev) # Default policy == 0x0003 will be used
c.add_valid("--boot firmware=efi --machine q35 --launchSecurity sev,reducedPhysBits=1,cbitpos=47 --connect " + utils.URIs.kvm_amd_sev) # Default policy == 0x0003 will be used
c.add_invalid("--launchSecurity policy=0x0001 --connect " + utils.URIs.kvm_amd_sev, grep="Missing mandatory attribute 'type'")
c.add_invalid("--boot uefi --launchSecurity sev --connect " + utils.URIs.kvm_amd_sev, grep="SEV launch security requires a Q35 UEFI machine")
c.add_invalid("--boot uefi --machine q35 --launchSecurity sev,policy=0x0001 --connect " + utils.URIs.kvm_x86, grep="SEV launch security is not supported") # Fail with no SEV capabilities

View File

@ -892,7 +892,6 @@ def add_guest_xml_options(geng):
ParserLaunchSecurity.register()
geng.add_argument("--launchSecurity", "--launchsecurity", action="append",
help=_("Configure VM launch security (e.g. SEV memory encryption). Ex:\n"
"--launchSecurity type=sev,cbitpos=47,reducedPhysBits=1,policy=0x0001,dhCert=BASE64CERT\n"
"--launchSecurity sev"))

View File

@ -18,27 +18,10 @@ class DomainLaunchSecurity(XMLBuilder):
dhCert = XMLProperty("./dhCert")
kernelHashes = XMLProperty("./@kernelHashes", is_yesno=True)
def is_sev(self):
return self.type == "sev"
def validate(self):
if not self.type:
raise RuntimeError(_("Missing mandatory attribute 'type'"))
def _set_defaults_sev(self, guest):
# SeaBIOS doesn't have support for SEV. Q35 defaults to virtio 1.0,
# which we need so let's not go through the 'virtio-transitional'
# exercise for pc-i440fx to make SEV work, AMD recommends Q35 anyway
# NOTE: at some point both of these platform checks should be put in
# validate(), once that accepts the 'guest' instance
if not guest.os.is_q35() or not guest.is_uefi():
raise RuntimeError(_("SEV launch security requires a Q35 UEFI machine"))
# libvirt or QEMU might not support SEV
domcaps = guest.lookup_domcaps()
if not domcaps.supports_sev_launch_security():
raise RuntimeError(_("SEV launch security is not supported on this platform"))
# '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:
@ -47,11 +30,6 @@ class DomainLaunchSecurity(XMLBuilder):
if self.policy is None:
self.policy = "0x03"
if self.cbitpos is None:
self.cbitpos = domcaps.features.sev.cbitpos
if self.reducedPhysBits is None:
self.reducedPhysBits = domcaps.features.sev.reducedPhysBits
def set_defaults(self, guest):
if self.is_sev():
if self.type == "sev":
return self._set_defaults_sev(guest)

View File

@ -93,8 +93,6 @@ def _make_capsblock(xml_root_name):
class _SEV(XMLBuilder):
XML_NAME = "sev"
supported = XMLProperty("./@supported", is_yesno=True)
cbitpos = XMLProperty("./cbitpos", is_int=True)
reducedPhysBits = XMLProperty("./reducedPhysBits", is_int=True)
#############################