[libvirt] [PATCH] qemu: De-duplicate some path definitions
by Michal Privoznik
There are some paths (e.g. /dev/vfio/vfio or /dev/mapper/control)
which are defined in qemu_domain.c and then in qemu_cgroup.c
again. This is suboptimal. Lets move paths into qemu_domain.h and
drop duplicate definitions.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_cgroup.c | 13 ++++++-------
src/qemu/qemu_domain.c | 30 +++++++++++-------------------
src/qemu/qemu_domain.h | 7 +++++++
src/qemu/qemu_hostdev.c | 5 +++--
4 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index ca76c4fdfa..19ca60905a 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -113,8 +113,6 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
}
-#define DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control"
-
static int
qemuSetupImageCgroupInternal(virDomainObjPtr vm,
virStorageSourcePtr src,
@@ -127,8 +125,8 @@ qemuSetupImageCgroupInternal(virDomainObjPtr vm,
}
if (virStoragePRDefIsManaged(src->pr) &&
- virFileExists(DEVICE_MAPPER_CONTROL_PATH) &&
- qemuSetupImagePathCgroup(vm, DEVICE_MAPPER_CONTROL_PATH, false) < 0)
+ virFileExists(QEMU_DEVICE_MAPPER_CONTROL_PATH) &&
+ qemuSetupImagePathCgroup(vm, QEMU_DEVICE_MAPPER_CONTROL_PATH, false) < 0)
return -1;
return qemuSetupImagePathCgroup(vm, src->path, src->readonly || forceReadonly);
@@ -162,7 +160,7 @@ qemuTeardownImageCgroup(virDomainObjPtr vm,
return 0;
}
- if (virFileExists(DEVICE_MAPPER_CONTROL_PATH)) {
+ if (virFileExists(QEMU_DEVICE_MAPPER_CONTROL_PATH)) {
for (i = 0; i < vm->def->ndisks; i++) {
virStorageSourcePtr diskSrc = vm->def->disks[i]->src;
@@ -176,9 +174,10 @@ qemuTeardownImageCgroup(virDomainObjPtr vm,
if (i == vm->def->ndisks) {
VIR_DEBUG("Disabling device mapper control");
ret = virCgroupDenyDevicePath(priv->cgroup,
- DEVICE_MAPPER_CONTROL_PATH, perms, true);
+ QEMU_DEVICE_MAPPER_CONTROL_PATH,
+ perms, true);
virDomainAuditCgroupPath(vm, priv->cgroup, "deny",
- DEVICE_MAPPER_CONTROL_PATH,
+ QEMU_DEVICE_MAPPER_CONTROL_PATH,
virCgroupGetDevicePermsString(perms), ret);
if (ret < 0)
return ret;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 0f1335de9c..7e6a9764c5 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -117,14 +117,6 @@ VIR_ENUM_IMPL(qemuDomainNamespace,
"mount",
);
-
-#define PROC_MOUNTS "/proc/mounts"
-#define DEVPREFIX "/dev/"
-#define DEV_VFIO "/dev/vfio/vfio"
-#define DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control"
-#define DEV_SEV "/dev/sev"
-
-
struct _qemuDomainLogContext {
virObject parent;
@@ -11872,7 +11864,7 @@ qemuDomainGetHostdevPath(virDomainDefPtr def,
tmpPerms[0] = perm;
if (includeVFIO) {
- if (VIR_STRDUP(tmpPaths[1], DEV_VFIO) < 0)
+ if (VIR_STRDUP(tmpPaths[1], QEMU_DEV_VFIO) < 0)
goto cleanup;
tmpPerms[1] = VIR_CGROUP_DEVICE_RW;
}
@@ -11919,7 +11911,7 @@ qemuDomainGetPreservedMountPath(virQEMUDriverConfigPtr cfg,
{
char *path = NULL;
char *tmp;
- const char *suffix = mountpoint + strlen(DEVPREFIX);
+ const char *suffix = mountpoint + strlen(QEMU_DEVPREFIX);
char *domname = virDomainDefGetShortName(vm->def);
size_t off;
@@ -11974,7 +11966,7 @@ qemuDomainGetPreservedMounts(virQEMUDriverConfigPtr cfg,
char **paths = NULL, **mounts = NULL;
size_t i, j, nmounts;
- if (virFileGetMountSubtree(PROC_MOUNTS, "/dev",
+ if (virFileGetMountSubtree(QEMU_PROC_MOUNTS, "/dev",
&mounts, &nmounts) < 0)
goto error;
@@ -12099,7 +12091,7 @@ qemuDomainCreateDeviceRecursive(const char *device,
* Otherwise we might get fooled with `/dev/../var/my_image'.
* For now, lets hope callers play nice.
*/
- if (STRPREFIX(device, DEVPREFIX)) {
+ if (STRPREFIX(device, QEMU_DEVPREFIX)) {
size_t i;
for (i = 0; i < data->ndevMountsPath; i++) {
@@ -12113,7 +12105,7 @@ qemuDomainCreateDeviceRecursive(const char *device,
/* Okay, @device is in /dev but not in any mount point under /dev.
* Create it. */
if (virAsprintf(&devicePath, "%s/%s",
- data->path, device + strlen(DEVPREFIX)) < 0)
+ data->path, device + strlen(QEMU_DEVPREFIX)) < 0)
goto cleanup;
if (virFileMakeParentPath(devicePath) < 0) {
@@ -12375,7 +12367,7 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
/* qemu-pr-helper might require access to /dev/mapper/control. */
if (disk->src->pr &&
- qemuDomainCreateDevice(DEVICE_MAPPER_CONTROL_PATH, data, true) < 0)
+ qemuDomainCreateDevice(QEMU_DEVICE_MAPPER_CONTROL_PATH, data, true) < 0)
goto cleanup;
ret = 0;
@@ -12707,7 +12699,7 @@ qemuDomainSetupLaunchSecurity(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
VIR_DEBUG("Setting up launch security");
- if (qemuDomainCreateDevice(DEV_SEV, data, false) < 0)
+ if (qemuDomainCreateDevice(QEMU_DEV_SEV, data, false) < 0)
return -1;
VIR_DEBUG("Set up launch security");
@@ -13122,7 +13114,7 @@ qemuDomainAttachDeviceMknodRecursive(virQEMUDriverPtr driver,
isReg = S_ISREG(data.sb.st_mode) || S_ISFIFO(data.sb.st_mode) || S_ISSOCK(data.sb.st_mode);
isDir = S_ISDIR(data.sb.st_mode);
- if ((isReg || isDir) && STRPREFIX(file, DEVPREFIX)) {
+ if ((isReg || isDir) && STRPREFIX(file, QEMU_DEVPREFIX)) {
cfg = virQEMUDriverGetConfig(driver);
if (!(target = qemuDomainGetPreservedMountPath(cfg, vm, file)))
goto cleanup;
@@ -13178,7 +13170,7 @@ qemuDomainAttachDeviceMknodRecursive(virQEMUDriverPtr driver,
}
# endif
- if (STRPREFIX(file, DEVPREFIX)) {
+ if (STRPREFIX(file, QEMU_DEVPREFIX)) {
size_t i;
for (i = 0; i < ndevMountsPath; i++) {
@@ -13287,7 +13279,7 @@ qemuDomainDetachDeviceUnlink(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
int ret = -1;
size_t i;
- if (STRPREFIX(file, DEVPREFIX)) {
+ if (STRPREFIX(file, QEMU_DEVPREFIX)) {
for (i = 0; i < ndevMountsPath; i++) {
if (STREQ(devMountsPath[i], "/dev"))
continue;
@@ -13429,7 +13421,7 @@ qemuDomainNamespaceSetupDisk(virDomainObjPtr vm,
/* qemu-pr-helper might require access to /dev/mapper/control. */
if (src->pr &&
- (VIR_STRDUP(dmPath, DEVICE_MAPPER_CONTROL_PATH) < 0 ||
+ (VIR_STRDUP(dmPath, QEMU_DEVICE_MAPPER_CONTROL_PATH) < 0 ||
VIR_APPEND_ELEMENT_COPY(paths, npaths, dmPath) < 0))
goto cleanup;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 5cb4a32c0e..3eea8b0f96 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -223,6 +223,13 @@ struct _qemuDomainUnpluggingDevice {
};
+#define QEMU_PROC_MOUNTS "/proc/mounts"
+#define QEMU_DEVPREFIX "/dev/"
+#define QEMU_DEV_VFIO "/dev/vfio/vfio"
+#define QEMU_DEV_SEV "/dev/sev"
+#define QEMU_DEVICE_MAPPER_CONTROL_PATH "/dev/mapper/control"
+
+
typedef enum {
QEMU_DOMAIN_NS_MOUNT = 0,
QEMU_DOMAIN_NS_LAST
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index cc0a4574cd..efa4d62f1f 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -25,6 +25,7 @@
#include <sys/ioctl.h>
#include "qemu_hostdev.h"
+#include "qemu_domain.h"
#include "virlog.h"
#include "virerror.h"
#include "viralloc.h"
@@ -140,7 +141,7 @@ qemuHostdevHostSupportsPassthroughVFIO(void)
return false;
/* condition 2 - /dev/vfio/vfio exists */
- if (!virFileExists("/dev/vfio/vfio"))
+ if (!virFileExists(QEMU_DEV_VFIO))
return false;
return true;
@@ -343,7 +344,7 @@ qemuHostdevPrepareMediatedDevices(virQEMUDriverPtr driver,
/* Checking for VFIO only is fine with mdev, as IOMMU isolation is achieved
* by the physical parent device.
*/
- supportsVFIO = virFileExists("/dev/vfio/vfio");
+ supportsVFIO = virFileExists(QEMU_DEV_VFIO);
for (i = 0; i < nhostdevs; i++) {
if (virHostdevIsMdevDevice(hostdevs[i])) {
--
2.21.0
5 years, 5 months
[libvirt] [PATCH v3] docs: Provide documentation for SEV launch security
by Erik Skultety
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
Since v2:
- incorporated Brijesh's notes into the SEV description and fixed the info
about SME
docs/launch_security_sev.html.in | 521 +++++++++++++++++++++++++++++++
1 file changed, 521 insertions(+)
create mode 100644 docs/launch_security_sev.html.in
diff --git a/docs/launch_security_sev.html.in b/docs/launch_security_sev.html.in
new file mode 100644
index 0000000000..923bb52b25
--- /dev/null
+++ b/docs/launch_security_sev.html.in
@@ -0,0 +1,521 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <h1>Launch security with AMD SEV</h1>
+
+ <ul id="toc"></ul>
+
+ <p>
+ Storage encryption in modern public cloud computing is a common practice.
+ However, from the point of view of a user of these cloud workloads, a
+ significant amount of trust needs to be put in the cloud platform security as
+ well as integrity (was the hypervisor tampered?). For this reason there's ever
+ rising demand for securing data in use, i.e. memory encryption.
+ One of the solutions addressing this matter is AMD SEV.
+ </p>
+
+ <h2>AMD SEV</h2>
+ <p>
+ SEV (Secure Encrypted Virtualization) is a feature extension of AMD's SME (Secure
+ Memory Encryption) intended for KVM virtual machines which is supported
+ primarily on AMD's EPYC CPU line. In contrast to SME, SEV uses a unique memory encryption
+ key for each VM. The whole encryption of memory pages is completely transparent
+ to the hypervisor and happens inside dedicated hardware in the on-die memory controller.
+ Each controller includes a high-performance Advanced Encryption Standard
+ (AES) engine that encrypts data when it is written to DRAM and decrypts it
+ when read.
+
+ For more details about the technology itself, you can visit
+ <a href="https://developer.amd.com/sev/">AMD's developer portal</a>.
+ </p>
+
+ <h2><a id="Host">Enabling SEV on the host</a></h2>
+ <p>
+ Before VMs can make use of the SEV feature you need to make sure your
+ AMD CPU does support SEV. You can check whether SEV is among the CPU
+ flags with:
+ </p>
+
+ <pre>
+$ cat /proc/cpuinfo | grep sev
+...
+sme ssbd sev ibpb</pre>
+
+ <p>
+ Next step is to enable SEV in the kernel, because it is disabled by default.
+ This is done by putting the following onto the kernel command line:
+ </p>
+
+ <pre>
+mem_encrypt=on kvm_amd.sev=1
+ </pre>
+
+ <p>
+ To make the changes persistent, append the above to the variable holding
+ parameters of the kernel command line in
+ <code>/etc/default/grub</code> to preserve SEV settings across reboots
+ </p>
+
+ <pre>
+$ cat /etc/default/grub
+...
+GRUB_CMDLINE_LINUX="... mem_encrypt=on kvm_amd.sev=1"
+$ grub2-mkconfig -o /boot/efi/EFI/<distro>/grub.cfg</pre>
+
+ <p>
+ <code>mem_encrypt=on</code> turns on the SME memory encryption feature on
+ the host which protects against the physical attack on the hypervisor
+ memory. The <code>kvm_amd.sev</code> parameter actually enables SEV in
+ the kvm module. It can be set on the command line alongside
+ <code>mem_encrypt</code> like shown above, or it can be put into a
+ module config under <code>/etc/modprobe.d/</code>
+ </p>
+
+ <pre>
+$ cat /etc/modprobe.d/sev.conf
+options kvm_amd sev=1
+ </pre>
+
+ <p>
+ After rebooting the host, you should see SEV being enabled in the kernel:
+ </p>
+
+ <pre>
+$ cat /sys/module/kvm_amd/parameters/sev
+1
+ </pre>
+
+ <h2><a id="Virt">Checking SEV support in the virt stack</a></h2>
+ <p>
+ <b>Note: All of the commands bellow need to be run with root privileges.</b>
+ </p>
+
+ <p>
+ First make sure you have the following packages in the specified versions:
+ </p>
+
+ <ul>
+ <li>
+ libvirt >= 4.5.0 (>5.1.0 recommended due to additional SEV bugfixes)
+ </li>
+ <li>
+ QEMU >= 2.12.0
+ </li>
+ </ul>
+ <p>
+ To confirm that the virtualization stack supports SEV, run the following:
+ </p>
+
+ <pre>
+# virsh domcapabilities
+<domainCapabilities>
+...
+ <features>
+ ...
+ <sev supported='yes'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ </sev>
+ ...
+ </features>
+</domainCapabilities></pre>
+ <p>
+ Note that if libvirt was already installed and libvirtd running before enabling SEV in the kernel followed by the host reboot you need to force libvirtd
+ to re-probe both the host and QEMU capabilities. First stop libvirtd:
+ </p>
+
+ <pre>
+# systemctl stop libvirtd.service
+ </pre>
+
+ <p>
+ Now you need to clean the capabilities cache:
+ </p>
+
+ <pre>
+# rm -f /var/cache/libvirt/qemu/capabilities/*
+ </pre>
+
+ <p>
+ If you now restart libvirtd, it will re-probe the capabilities and if
+ you now run:
+ </p>
+
+ <pre>
+# virsh domcapabilities
+ </pre>
+
+ <p>
+ SEV should be listed as supported. If you still see:
+ </p>
+
+ <pre>
+<sev supported='no'/>
+ </pre>
+
+ <p>
+ it means one of two things:
+ <ol>
+ <li>
+ libvirt does support SEV, but either QEMU or the host does not
+ </li>
+ <li>
+ you have libvirt <=5.1.0 which suffered from getting a
+ <code>'Permission denied'</code> on <code>/dev/sev</code> because
+ of the default permissions on the character device which prevented
+ QEMU from opening it during capabilities probing - you can either
+ manually tweak the permissions so that QEMU has access to it or
+ preferably install libvirt 5.1.0 or higher
+ </li>
+ </ol>
+ </p>
+
+ <h2><a id="Configuration">VM Configuration</a></h2>
+ <p>
+ SEV is enabled in the XML by specifying the
+ <a href="https://libvirt.org/formatdomain.html#launchSecurity"><launchSecurity> </a> element. However, specifying <code>launchSecurity</code> isn't
+ enough to boot an SEV VM. Further configuration requirements are discussed
+ below.
+ </p>
+
+ <h3><a id="Machine">Machine type</a></h3>
+ <p>
+ Even though both Q35 and legacy PC machine types (for PC see also
+ "virtio") can be used with SEV, usage of the legacy PC machine type is
+ strongly discouraged, since depending on how your OVMF package was
+ built (e.g. including features like SecureBoot or SMM) Q35 may even be
+ required.
+ </p>
+
+ <h5>Q35</h5>
+<pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ ...
+</os>
+...</pre>
+
+ <h5>i440fx (discouraged)</h5>
+ <pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-i440fx-3.0'>hvm</type>
+ ...
+</os>
+...
+ </pre>
+
+ <h3><a id="Boot">Boot loader</a></h3>
+ <p>
+ SEV is only going to work with OVMF (UEFI), so you'll need to point libvirt to
+ the correct OVMF binary.
+ </p>
+ <pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+</os>
+...</pre>
+
+ <h3><a id="Memory">Memory</a></h3>
+ <p>
+ Internally, SEV expects that the encrypted memory pages won't be swapped out or move
+ around so the VM memory needs to be pinned in physical RAM which will be
+ handled by QEMU. Apart from that, certain memory regions allocated by QEMU
+ itself (UEFI pflash, device ROMs, video RAM, etc.) have to be encrypted as
+ well. This causes a conflict in how libvirt tries to protect the host.
+ By default, libvirt enforces a memory hard limit on each VM's cgroup in order
+ to protect the host from malicious QEMU to allocate and lock all the available
+ memory. This limit corresponds to the total memory allocation for the VM given
+ by <code><currentMemory></code> element. However, trying to account for the additional
+ memory regions QEMU allocates when calculating the limit in an automated manner
+ is non-deterministic. One way to resolve this is to set the hard limit manually.
+
+ <p>
+ Note: Figuring out the right number so that your guest boots and isn't killed is
+ challenging, but 256MiB extra memory over the total guest RAM should suffice for
+ most workloads and may serve as a good starting point.
+
+ For example, a domain with 4GB memory with a 256MiB extra hard limit would look
+ like this:
+ </p>
+ </p>
+
+ <pre>
+# virsh edit <domain>
+<domain>
+ ...
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>4456448</hard_limit>
+ </memtune>
+ ...
+</domain></pre>
+ <p>
+ There's another, preferred method of taking care of the limits by
+ using the<code><memoryBacking></code> element along with the
+ <code><locked/></code> subelement:
+ </p>
+
+ <pre>
+<domain>
+ ...
+ <memoryBacking>
+ <locked/>
+ </memoryBacking>
+ ...
+</domain></pre>
+
+ <p>
+ What that does is that it tells libvirt not to force any hard limit (well,
+ unlimited) upon the VM cgroup. The obvious advantage is that one doesn't need
+ to determine the hard limit for every single SEV-enabled VM. However, there is
+ a significant security-related drawback to this approach. Since no hard limit
+ is applied, a malicious QEMU could perform a DoS attack by locking all of the
+ host's available memory. The way to avoid this issue and to protect the host is
+ to enforce a bigger hard limit on the master cgroup containing all of the VMs
+ - on systemd this is <code>machine.slice</code>.
+ </p>
+
+ <pre>
+# systemctl set-property machine.slice MemoryHigh=<value></pre>
+
+ <p>
+ To put even stricter measures in place which would involve the OOM killer, use
+ <pre>
+# systemctl set-property machine.slice MemoryMax=<value></pre>
+ instead. Alternatively, you can create a systemd config (don't forget
+ to reload systemd configuration in this case):
+ <pre>
+# cat << EOF > /etc/systemd/system.control/machine.slice.d/90-MemoryMax.conf
+MemoryMax=<value>
+EOF</pre>
+ The trade-off to keep in mind with the second approach is that the VMs
+ can still perform DoS on each other.
+ </p>
+
+ <h3><a id="Virtio">Virtio</a></h3>
+ <p>
+ In order to make virtio devices work, we need to enable emulated IOMMU
+ on the devices so that virtual DMA can work.
+ </p>
+
+ <pre>
+# virsh edit <domain>
+<domain>
+ ...
+ <controller type='virtio-serial' index='0'>
+ <driver iommu='on'/>
+ </controller>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <driver iommu='on'/>
+ </controller>
+ ...
+ <memballoon model='virtio'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio'>
+ <backend model='random'>/dev/urandom</backend>
+ <driver iommu='on'/>
+ </rng>
+ ...
+<domain></pre>
+
+ <p>
+ If you for some reason want to use the legacy PC machine type, further changes
+ to the virtio
+ configuration is required, because SEV will not work with Virtio <1.0. In
+ libvirt, this is handled by using the virtio-non-transitional device model
+ (libvirt >= 5.2.0 required).
+
+ <p>
+ Note: some devices like video devices don't
+ support non-transitional model, which means that virtio GPU cannot be used.
+ </p>
+ </p>
+
+ <pre>
+<domain>
+ ...
+ <devices>
+ ...
+ <memballoon model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </memballoon>
+ </devices>
+ ...
+</domain></pre>
+
+ <h2><a id="Limitations">Limitations</a></h2>
+ <p>
+ Currently, the boot disk cannot be of type virtio-blk, instead, virtio-scsi
+ needs to be used if virtio is desired. This limitation is expected to be lifted
+ with future releases of kernel (the kernel used at the time of writing the
+ article is 5.0.14).
+ If you still cannot start an SEV VM, it could be because of wrong SELinux label on the <code>/dev/sev</code> device with selinux-policy <3.14.2.40 which prevents QEMU from touching the device. This can be resolved by upgrading the package, tuning the selinux policy rules manually to allow svirt_t to access the device (see <code>audit2allow</code> on how to do that) or putting SELinux into permissive mode (discouraged).
+ </p>
+
+ <h2><a id="Examples">Full domain XML examples</a></h2>
+
+ <h5>Q35 machine</h5>
+ <pre>
+<domain type='kvm'>
+ <name>sev-dummy</name>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memoryBacking>
+ <locked/>
+ </memoryBacking>
+ <vcpu placement='static'>4</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+ <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <vmport state='off'/>
+ </features>
+ <cpu mode='host-model' check='partial'>
+ <model fallback='allow'/>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/sev-dummy.qcow2'/>
+ <target dev='sda' bus='scsi'/>
+ <boot order='1'/>
+ </disk>
+ <controller type='virtio-serial' index='0'>
+ <driver iommu='on'/>
+ </controller>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <driver iommu='on'/>
+ </controller>
+ <interface type='network'>
+ <mac address='52:54:00:cc:56:90'/>
+ <source network='default'/>
+ <model type='virtio'/>
+ <driver iommu='on'/>
+ </interface>
+ <graphics type='spice' autoport='yes'>
+ <listen type='address'/>
+ <gl enable='no'/>
+ </graphics>
+ <video>
+ <model type='qxl'/>
+ </video>
+ <memballoon model='virtio'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio'>
+ <driver iommu='on'/>
+ </rng>
+ </devices>
+ <launchSecurity type='sev'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x0003</policy>
+ </launchSecurity>
+</domain></pre>
+
+ <h5>PC-i440fx machine:</h5>
+ <pre>
+<domain type='kvm'>
+ <name>sev-dummy-legacy</name>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>5242880</hard_limit>
+ </memtune>
+ <vcpu placement='static'>4</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+ <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <vmport state='off'/>
+ </features>
+ <cpu mode='host-model' check='partial'>
+ <model fallback='allow'/>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/sev-dummy-seabios.qcow2'/>
+ <target dev='sda' bus='sata'/>
+ </disk>
+ <interface type='network'>
+ <mac address='52:54:00:d8:96:c8'/>
+ <source network='default'/>
+ <model type='virtio-non-transitional'/>
+ </interface>
+ <serial type='pty'>
+ <target type='isa-serial' port='0'>
+ <model name='isa-serial'/>
+ </target>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='tablet' bus='usb'>
+ <address type='usb' bus='0' port='1'/>
+ </input>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='spice' autoport='yes'>
+ <listen type='address'/>
+ <gl enable='no'/>
+ </graphics>
+ <video>
+ <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
+ </video>
+ <memballoon model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </rng>
+ </devices>
+ <launchSecurity type='sev'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x0003</policy>
+ </launchSecurity>
+</domain></pre>
+ </body>
+</html>
--
2.21.0
5 years, 5 months
[libvirt] Release of libvirt-5.5.0
by Daniel Veillard
It's there, only one day late :-) tagged in git as with signed tarball
and source rpms uploaded to the usual place:
https://libvirt.org/sources/
I also released the python bindings that you can find at:
https://libvirt.org/sources/python/
This is a rich release with security fixes, new APIs, some deprecated features
and as usual improvements and bug fixes !
Security:
- api: Prevent access to several APIs over read-only connections
Certain APIs give root-equivalent access to the host, and as such
should be limited to privileged users. CVE-2019-10161, CVE-2019-10166,
CVE-2019-10167, CVE-2019-10168.
New features:
- qemu: Support SMMUv3 IOMMU
SMMUv3 is an IOMMU implementation for ARM virt guests.
- network: Introduce the network port API
This new public API can be used by virtualization drivers to manage
network resources associated with guests, and is a further step towards
splitting libvirtd into multiple daemons.
Removed features:
- qemu: Remove support for virDomainQemuAttach and
virConnectDomainXMLFromNative APIs
The qemu implementations for the APIs mentioned above were removed and
the APIs now return an error. The implementation was stale for a long
time and did not work with modern QEMU command lines, generated from
libvirt or otherwise.
- Stop supporting migration of config files from pre-XDG layout
The new layout was introduced with libvirt 0.9.13 (Jul 2012).
- Remove Avahi mDNS support
This feature was never used outside of virt-manager, which has itself
stopped using it a while ago.
Improvements:
- sysinfo: Report SMBIOS information on aarch64
While SMBIOS support has historically been limited to x86_64, modern
aarch64 machines often offer access to the same information as well,
and libvirt now exposes it to the user when that's the case.
- test driver: Expand API coverage
Even more APIs that were missing from the test driver have now been
implemented.
- virt-xml-validate: Allow input to be read from stdin
- qemu: Validate spapr-vio addresses as 32-bit
libvirt has always considered these addresses (used for pSeries guests)
as 64-bit, but the sPAPR specification says that they're 32-bit
instead.
Bug fixes:
- qemu: Set process affinity correctly when using <numatune>
libvirt would mistakenly interpret the nodeset attribute as a list of
CPUs instead of as a list of NUMA node, and the process affinity would
be set incorrectly as a result; this has now been fixed.
Thanks everybody for your help with this release, be that with bugs, fixes,
reviews, documentation, localisation, etc ...
Enjoy the release,
Daniel
--
Daniel Veillard | Red Hat Developers Tools http://developer.redhat.com/
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
5 years, 5 months
[libvirt] [PATCH 0/2] tests: Add and use more DO_TEST_CAPS_*() macros
by Andrea Bolognani
Andrea Bolognani (2):
tests: Add more DO_TEST_CAPS_*() macros
tests: Use the new DO_TEST_CAPS_*() macros
tests/qemuxml2argvtest.c | 76 ++++++++++++++++++++--------------------
tests/qemuxml2xmltest.c | 32 +++++++++--------
2 files changed, 55 insertions(+), 53 deletions(-)
--
2.21.0
5 years, 5 months
[libvirt] [PATCH v2] docs: Provide documentation for SEV launch security
by Erik Skultety
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
docs/launch_security_sev.html.in | 516 +++++++++++++++++++++++++++++++
1 file changed, 516 insertions(+)
create mode 100644 docs/launch_security_sev.html.in
diff --git a/docs/launch_security_sev.html.in b/docs/launch_security_sev.html.in
new file mode 100644
index 0000000000..2f0f89d714
--- /dev/null
+++ b/docs/launch_security_sev.html.in
@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <h1>Launch security with AMD SEV</h1>
+
+ <ul id="toc"></ul>
+
+ <p>
+ Storage encryption in modern public cloud computing is a common practice.
+ However, from the point of view of a user of these cloud workloads, a
+ significant amount of trust needs to be put in the cloud platform security as
+ well as integrity (was the hypervisor tampered?). For this reason there's ever
+ rising demand for securing data in use, i.e. memory encryption.
+ One of the solutions addressing this matter is AMD SEV.
+ </p>
+
+ <h2>AMD SEV</h2>
+ <p>
+ SEV (Secure Encrypted Virtualization) is a feature extension of AMD's SME (Secure
+ Memory Encryption) intended for KVM virtual machines which is supported
+ primarily on AMD's EPYC CPU line. In contrast to SME, SEV uses a unique memory encryption
+ key for each VM. The whole encryption of memory pages is completely transparent
+ to the hypervisor and happens in the AMD firmware.
+ For more details about the technology itself, you can visit
+ <a href="https://developer.amd.com/sev/">AMD's developer portal</a>.
+ </p>
+
+ <h2><a id="Host">Enabling SEV on the host</a></h2>
+ <p>
+ Before VMs can make use of the SEV feature you need to make sure your
+ AMD CPU does support SEV. You can check whether SEV is among the CPU
+ flags with:
+ </p>
+
+ <pre>
+$ cat /proc/cpuinfo | grep sev
+...
+sme ssbd sev ibpb</pre>
+
+ <p>
+ Next step is to enable SEV in the kernel, because it is disabled by default.
+ This is done by putting the following onto the kernel command line:
+ </p>
+
+ <pre>
+mem_encrypt=on kvm_amd.sev=1
+ </pre>
+
+ <p>
+ To make the changes persistent, append the above to the variable holding
+ parameters of the kernel command line in
+ <code>/etc/default/grub</code> to preserve SEV settings across reboots
+ </p>
+
+ <pre>
+$ cat /etc/default/grub
+...
+GRUB_CMDLINE_LINUX="... mem_encrypt=on kvm_amd.sev=1"
+$ grub2-mkconfig -o /boot/efi/EFI/<distro>/grub.cfg</pre>
+
+ <p>
+ <code>mem_encrypt=on</code> turns on the SME memory encryption feature on
+ the host which is required for SEV to work. The <code>kvm_amd.sev</code>
+ parameter actually enables SEV in the kvm module. It can be set on the
+ command line alongside <code>mem_encrypt</code> like shown above, or it
+ can be put into a module config under <code>/etc/modprobe.d/</code>
+ </p>
+
+ <pre>
+$ cat /etc/modprobe.d/sev.conf
+options kvm_amd sev=1
+ </pre>
+
+ <p>
+ After rebooting the host, you should see SEV being enabled in the kernel:
+ </p>
+
+ <pre>
+$ cat /sys/module/kvm_amd/parameters/sev
+1
+ </pre>
+
+ <h2><a id="Virt">Checking SEV support in the virt stack</a></h2>
+ <p>
+ <b>Note: All of the commands bellow need to be run with root privileges.</b>
+ </p>
+
+ <p>
+ First make sure you have the following packages in the specified versions:
+ </p>
+
+ <ul>
+ <li>
+ libvirt >= 4.5.0 (>5.1.0 recommended due to additional SEV bugfixes)
+ </li>
+ <li>
+ QEMU >= 2.12.0
+ </li>
+ </ul>
+ <p>
+ To confirm that the virtualization stack supports SEV, run the following:
+ </p>
+
+ <pre>
+# virsh domcapabilities
+<domainCapabilities>
+...
+ <features>
+ ...
+ <sev supported='yes'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ </sev>
+ ...
+ </features>
+</domainCapabilities></pre>
+ <p>
+ Note that if libvirt was already installed and libvirtd running before enabling SEV in the kernel followed by the host reboot you need to force libvirtd
+ to re-probe both the host and QEMU capabilities. First stop libvirtd:
+ </p>
+
+ <pre>
+# systemctl stop libvirtd.service
+ </pre>
+
+ <p>
+ Now you need to clean the capabilities cache:
+ </p>
+
+ <pre>
+# rm -f /var/cache/libvirt/qemu/capabilities/*
+ </pre>
+
+ <p>
+ If you now restart libvirtd, it will re-probe the capabilities and if
+ you now run:
+ </p>
+
+ <pre>
+# virsh domcapabilities
+ </pre>
+
+ <p>
+ SEV should be listed as supported. If you still see:
+ </p>
+
+ <pre>
+<sev supported='no'/>
+ </pre>
+
+ <p>
+ it means one of two things:
+ <ol>
+ <li>
+ libvirt does support SEV, but either QEMU or the host does not
+ </li>
+ <li>
+ you have libvirt <=5.1.0 which suffered from getting a
+ <code>'Permission denied'</code> on <code>/dev/sev</code> because
+ of the default permissions on the character device which prevented
+ QEMU from opening it during capabilities probing - you can either
+ manually tweak the permissions so that QEMU has access to it or
+ preferably install libvirt 5.1.0 or higher
+ </li>
+ </ol>
+ </p>
+
+ <h2><a id="Configuration">VM Configuration</a></h2>
+ <p>
+ SEV is enabled in the XML by specifying the
+ <a href="https://libvirt.org/formatdomain.html#launchSecurity"><launchSecurity> </a> element. However, specifying <code>launchSecurity</code> isn't
+ enough to boot an SEV VM. Further configuration requirements are discussed
+ below.
+ </p>
+
+ <h3><a id="Machine">Machine type</a></h3>
+ <p>
+ Even though both Q35 and legacy PC machine types (for PC see also
+ "virtio") can be used with SEV, usage of the legacy PC machine type is
+ strongly discouraged, since depending on how your OVMF package was
+ built (e.g. including features like SecureBoot or SMM) Q35 may even be
+ required.
+ </p>
+
+ <h5>Q35</h5>
+<pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ ...
+</os>
+...</pre>
+
+ <h5>i440fx (discouraged)</h5>
+ <pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-i440fx-3.0'>hvm</type>
+ ...
+</os>
+...
+ </pre>
+
+ <h3><a id="Boot">Boot loader</a></h3>
+ <p>
+ SEV is only going to work with OVMF (UEFI), so you'll need to point libvirt to
+ the correct OVMF binary.
+ </p>
+ <pre>
+...
+<os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+</os>
+...</pre>
+
+ <h3><a id="Memory">Memory</a></h3>
+ <p>
+ Internally, SEV expects that the encrypted memory pages won't be swapped out or move
+ around so the VM memory needs to be pinned in physical RAM which will be
+ handled by QEMU. Apart from that, certain memory regions allocated by QEMU
+ itself (UEFI pflash, device ROMs, video RAM, etc.) have to be encrypted as
+ well. This causes a conflict in how libvirt tries to protect the host.
+ By default, libvirt enforces a memory hard limit on each VM's cgroup in order
+ to protect the host from malicious QEMU to allocate and lock all the available
+ memory. This limit corresponds to the total memory allocation for the VM given
+ by <code><currentMemory></code> element. However, trying to account for the additional
+ memory regions QEMU allocates when calculating the limit in an automated manner
+ is non-deterministic. One way to resolve this is to set the hard limit manually.
+
+ <p>
+ Note: Figuring out the right number so that your guest boots and isn't killed is
+ challenging, but 256MiB extra memory over the total guest RAM should suffice for
+ most workloads and may serve as a good starting point.
+
+ For example, a domain with 4GB memory with a 256MiB extra hard limit would look
+ like this:
+ </p>
+ </p>
+
+ <pre>
+# virsh edit <domain>
+<domain>
+ ...
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>4456448</hard_limit>
+ </memtune>
+ ...
+</domain></pre>
+ <p>
+ There's another, preferred method of taking care of the limits by
+ using the<code><memoryBacking></code> element along with the
+ <code><locked/></code> subelement:
+ </p>
+
+ <pre>
+<domain>
+ ...
+ <memoryBacking>
+ <locked/>
+ </memoryBacking>
+ ...
+</domain></pre>
+
+ <p>
+ What that does is that it tells libvirt not to force any hard limit (well,
+ unlimited) upon the VM cgroup. The obvious advantage is that one doesn't need
+ to determine the hard limit for every single SEV-enabled VM. However, there is
+ a significant security-related drawback to this approach. Since no hard limit
+ is applied, a malicious QEMU could perform a DoS attack by locking all of the
+ host's available memory. The way to avoid this issue and to protect the host is
+ to enforce a bigger hard limit on the master cgroup containing all of the VMs
+ - on systemd this is <code>machine.slice</code>.
+ </p>
+
+ <pre>
+# systemctl set-property machine.slice MemoryHigh=<value></pre>
+
+ <p>
+ To put even stricter measures in place which would involve the OOM killer, use
+ <pre>
+# systemctl set-property machine.slice MemoryMax=<value></pre>
+ instead. Alternatively, you can create a systemd config (don't forget
+ to reload systemd configuration in this case):
+ <pre>
+# cat << EOF > /etc/systemd/system.control/machine.slice.d/90-MemoryMax.conf
+MemoryMax=<value>
+EOF</pre>
+ The trade-off to keep in mind with the second approach is that the VMs
+ can still perform DoS on each other.
+ </p>
+
+ <h3><a id="Virtio">Virtio</a></h3>
+ <p>
+ In order to make virtio devices work, we need to enable emulated IOMMU
+ on the devices so that virtual DMA can work.
+ </p>
+
+ <pre>
+# virsh edit <domain>
+<domain>
+ ...
+ <controller type='virtio-serial' index='0'>
+ <driver iommu='on'/>
+ </controller>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <driver iommu='on'/>
+ </controller>
+ ...
+ <memballoon model='virtio'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio'>
+ <backend model='random'>/dev/urandom</backend>
+ <driver iommu='on'/>
+ </rng>
+ ...
+<domain></pre>
+
+ <p>
+ If you for some reason want to use the legacy PC machine type, further changes
+ to the virtio
+ configuration is required, because SEV will not work with Virtio <1.0. In
+ libvirt, this is handled by using the virtio-non-transitional device model
+ (libvirt >= 5.2.0 required).
+
+ <p>
+ Note: some devices like video devices don't
+ support non-transitional model, which means that virtio GPU cannot be used.
+ </p>
+ </p>
+
+ <pre>
+<domain>
+ ...
+ <devices>
+ ...
+ <memballoon model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </memballoon>
+ </devices>
+ ...
+</domain></pre>
+
+ <h2><a id="Limitations">Limitations</a></h2>
+ <p>
+ Currently, the boot disk cannot be of type virtio-blk, instead, virtio-scsi
+ needs to be used if virtio is desired. This limitation is expected to be lifted
+ with future releases of kernel (the kernel used at the time of writing the
+ article is 5.0.14).
+ If you still cannot start an SEV VM, it could be because of wrong SELinux label on the <code>/dev/sev</code> device with selinux-policy <3.14.2.40 which prevents QEMU from touching the device. This can be resolved by upgrading the package, tuning the selinux policy rules manually to allow svirt_t to access the device (see <code>audit2allow</code> on how to do that) or putting SELinux into permissive mode (discouraged).
+ </p>
+
+ <h2><a id="Examples">Full domain XML examples</a></h2>
+
+ <h5>Q35 machine</h5>
+ <pre>
+<domain type='kvm'>
+ <name>sev-dummy</name>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memoryBacking>
+ <locked/>
+ </memoryBacking>
+ <vcpu placement='static'>4</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-q35-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+ <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <vmport state='off'/>
+ </features>
+ <cpu mode='host-model' check='partial'>
+ <model fallback='allow'/>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/sev-dummy.qcow2'/>
+ <target dev='sda' bus='scsi'/>
+ <boot order='1'/>
+ </disk>
+ <controller type='virtio-serial' index='0'>
+ <driver iommu='on'/>
+ </controller>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <driver iommu='on'/>
+ </controller>
+ <interface type='network'>
+ <mac address='52:54:00:cc:56:90'/>
+ <source network='default'/>
+ <model type='virtio'/>
+ <driver iommu='on'/>
+ </interface>
+ <graphics type='spice' autoport='yes'>
+ <listen type='address'/>
+ <gl enable='no'/>
+ </graphics>
+ <video>
+ <model type='qxl'/>
+ </video>
+ <memballoon model='virtio'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio'>
+ <driver iommu='on'/>
+ </rng>
+ </devices>
+ <launchSecurity type='sev'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x0003</policy>
+ </launchSecurity>
+</domain></pre>
+
+ <h5>PC-i440fx machine:</h5>
+ <pre>
+<domain type='kvm'>
+ <name>sev-dummy-legacy</name>
+ <memory unit='KiB'>4194304</memory>
+ <currentMemory unit='KiB'>4194304</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>5242880</hard_limit>
+ </memtune>
+ <vcpu placement='static'>4</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-3.0'>hvm</type>
+ <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader>
+ <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <vmport state='off'/>
+ </features>
+ <cpu mode='host-model' check='partial'>
+ <model fallback='allow'/>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/var/lib/libvirt/images/sev-dummy-seabios.qcow2'/>
+ <target dev='sda' bus='sata'/>
+ </disk>
+ <interface type='network'>
+ <mac address='52:54:00:d8:96:c8'/>
+ <source network='default'/>
+ <model type='virtio-non-transitional'/>
+ </interface>
+ <serial type='pty'>
+ <target type='isa-serial' port='0'>
+ <model name='isa-serial'/>
+ </target>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='tablet' bus='usb'>
+ <address type='usb' bus='0' port='1'/>
+ </input>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='spice' autoport='yes'>
+ <listen type='address'/>
+ <gl enable='no'/>
+ </graphics>
+ <video>
+ <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1' primary='yes'/>
+ </video>
+ <memballoon model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </memballoon>
+ <rng model='virtio-non-transitional'>
+ <driver iommu='on'/>
+ </rng>
+ </devices>
+ <launchSecurity type='sev'>
+ <cbitpos>47</cbitpos>
+ <reducedPhysBits>1</reducedPhysBits>
+ <policy>0x0003</policy>
+ </launchSecurity>
+</domain></pre>
+ </body>
+</html>
--
2.21.0
5 years, 5 months
[libvirt] [PATCH 0/4] test_driver: implement some DomainGetParametersAPIs
by Ilias Stamatis
Ilias Stamatis (4):
test_driver: introduce TEST_SET_PARAM macro
test_driver: implement virDomainGetMemoryParameters
test_driver: implement virDomainGetNumaParameters
test_driver: implement testDomainGetInterfaceParameters
src/test/test_driver.c | 157 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
--
2.22.0
5 years, 5 months
[libvirt] [PATCH] test_driver: fix some bugs on testDomainGetDiskErrors
by Ilias Stamatis
The current implementation has the following bugs:
- the vm variable is accessed after calling virDomainObjEndAPI on it
- if VIR_STRDUP fails and we jump to the cleanup section, we're calling
VIR_FREE on pointers for which we haven't allocated memory
- the error type VIR_DOMAIN_DISK_ERROR_NONE is used which contradicts
the documentation of the API that says that disks with no errors are not
reported
This patch fixes all of them and additionally reports errors only for
every second disk (instead of reporting errors for all disks) which was
the initial intention.
Signed-off-by: Ilias Stamatis <stamatis.iliass(a)gmail.com>
---
src/test/test_driver.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 2a0ffbc6c5..a7e40112d1 100755
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -3246,6 +3246,7 @@ static int testDomainGetDiskErrors(virDomainPtr dom,
unsigned int flags)
{
virDomainObjPtr vm = NULL;
+ int n = 0;
int ret = -1;
size_t i;
@@ -3258,12 +3259,13 @@ static int testDomainGetDiskErrors(virDomainPtr dom,
goto cleanup;
if (errors) {
- for (i = 0; i < MIN(vm->def->ndisks, maxerrors); i++) {
- if (VIR_STRDUP(errors[i].disk, vm->def->disks[i]->dst) < 0)
+ for (i = 1; i < vm->def->ndisks && n < maxerrors; i += 2) {
+ if (VIR_STRDUP(errors[n].disk, vm->def->disks[i]->dst) < 0)
goto cleanup;
- errors[i].error = i % VIR_DOMAIN_DISK_ERROR_LAST;
+ errors[n].error = (n % (VIR_DOMAIN_DISK_ERROR_LAST - 1)) + 1;
+ n++;
}
- ret = i;
+ ret = n;
} else {
ret = vm->def->ndisks;
}
@@ -3271,7 +3273,7 @@ static int testDomainGetDiskErrors(virDomainPtr dom,
cleanup:
virDomainObjEndAPI(&vm);
if (ret < 0) {
- for (i = 0; i < MIN(vm->def->ndisks, maxerrors); i++)
+ for (i = 0; i < n; i++)
VIR_FREE(errors[i].disk);
}
return ret;
--
2.22.0
5 years, 5 months
[libvirt] Checking the expected behavior on dynamic image file ownership when live migrating
by Christian Ehrhardt
Hi,
today I was debugging an issue that I found with qemu 4.0 and ended up
puzzled about file ownership. I'm almost EOD now, but wanted to reach
out here for a sanity check before I debug further. The case
sumamrized is this:
1. start guest
1.1 image files are changed to libvirt-qemu:kvm (which matches
Ubuntus user/group config)
2. live migrate the guest to a different node
2.1 image files go back to root:root which they initially had (ok)
3. migrate guest back to the original node
x. image files stay root:root and are not changed back to libvirt-qemu:kvm
That is odd/unexpected, but it seems the same applies to older
versions and there it was never a problem so far.
In my case I stumbled over it because the newer qemu --copy-storage-*
options now want to re-open the file at some point and that fails
with:
error: internal error: unable to execute QEMU command 'drive-mirror':
Could not reopen file: Permission denied
If I e.g. shut down and start the guest on the source node (which
fixes up the ownership at runtime) then migration with copy-storage
works fine again.
I'm mostly looking for hints if this is a known issue or being worked
on to not waste time tomorrow.
So hints are welcome.
--
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
5 years, 5 months
[libvirt] [PATCH v2] test_driver: implement virDomainGetMemoryParameters
by Ilias Stamatis
Signed-off-by: Ilias Stamatis <stamatis.iliass(a)gmail.com>
---
Things changed since v1:
- virDomainObjGetOneDef is used in order to get the appropriate def
- the TEST_ASSIGN_MEM_PARAM macro got removed
src/test/test_driver.c | 52 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 4b1f2724a0..01b3ed88f3 100755
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -2514,6 +2514,57 @@ testDomainGetMaxVcpus(virDomainPtr domain)
VIR_DOMAIN_VCPU_MAXIMUM));
}
+
+static int
+testDomainGetMemoryParameters(virDomainPtr dom,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ int ret = -1;
+ virDomainObjPtr vm = NULL;
+ virDomainDefPtr def = NULL;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+ if ((*nparams) == 0) {
+ *nparams = 3;
+ return 0;
+ }
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (!(def = virDomainObjGetOneDef(vm, flags)))
+ goto cleanup;
+
+ if (*nparams > 0 &&
+ virTypedParameterAssign(¶ms[0], VIR_DOMAIN_MEMORY_HARD_LIMIT,
+ VIR_TYPED_PARAM_ULLONG, def->mem.hard_limit) < 0)
+ goto cleanup;
+
+ if (*nparams > 1 &&
+ virTypedParameterAssign(¶ms[1], VIR_DOMAIN_MEMORY_SOFT_LIMIT,
+ VIR_TYPED_PARAM_ULLONG, def->mem.soft_limit) < 0)
+ goto cleanup;
+
+ if (*nparams > 2 &&
+ virTypedParameterAssign(¶ms[2], VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT,
+ VIR_TYPED_PARAM_ULLONG, def->mem.swap_hard_limit) < 0)
+ goto cleanup;
+
+ if (*nparams > 3)
+ *nparams = 3;
+
+ ret = 0;
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
static int
testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus,
unsigned int flags)
@@ -7275,6 +7326,7 @@ static virHypervisorDriver testHypervisorDriver = {
.domainGetVcpus = testDomainGetVcpus, /* 0.7.3 */
.domainGetVcpuPinInfo = testDomainGetVcpuPinInfo, /* 1.2.18 */
.domainGetMaxVcpus = testDomainGetMaxVcpus, /* 0.7.3 */
+ .domainGetMemoryParameters = testDomainGetMemoryParameters, /* 5.6.0 */
.domainGetXMLDesc = testDomainGetXMLDesc, /* 0.1.4 */
.connectListDefinedDomains = testConnectListDefinedDomains, /* 0.1.11 */
.connectNumOfDefinedDomains = testConnectNumOfDefinedDomains, /* 0.1.11 */
--
2.22.0
5 years, 5 months