From nobody Sun Feb 8 10:53:24 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) client-ip=207.211.31.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1574434073; cv=none; d=zohomail.com; s=zohoarc; b=MGYR7NBn2E9WokyXxaZweOMdbnrCy0dgP161cNbnixsqSlnvb/1Ex4rdAKTUnq6NKJVVgvNWvg4mjNY6ga7RL+p9tpzhhdr2zYLR35Ac0zYB+AWQAnIqkoR9BkMhRjqktFBN8iwrd6D66mJ5m8NqhjB7bGUsIcBQa2zlT3thkKY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1574434073; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Ptrjt9X25JjUTDH8iyaRmVz89LOPgkYuBTGivxPxzu4=; b=NFOdiZZ7Vgyljqu+JfQwaTuMKO+RrKKyxaORdHmN2BigCPlFuW2Uf/w1rMP4uYl5TDtcrhWGZkBHer7911DgyPtMrekKfkE5XFxYQ6d3PBqhlkU5UEhbyV/bnsNcYejz6MzlfWX4nQEAgxPsR4/gbHJxsxkZApVmOKBaCZQovRw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by mx.zohomail.com with SMTPS id 1574434073560981.13245756814; Fri, 22 Nov 2019 06:47:53 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-219-JCsGmg1hODWuhUiRHrQGrA-1; Fri, 22 Nov 2019 09:47:50 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A39ECDB75; Fri, 22 Nov 2019 14:47:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 783E035F4; Fri, 22 Nov 2019 14:47:43 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 0F9664E573; Fri, 22 Nov 2019 14:47:43 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id xAMElfUD018209 for ; Fri, 22 Nov 2019 09:47:41 -0500 Received: by smtp.corp.redhat.com (Postfix) id 1C9401036C8D; Fri, 22 Nov 2019 14:47:41 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-49.ams2.redhat.com [10.36.112.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3CB871036C7E; Fri, 22 Nov 2019 14:47:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1574434072; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Ptrjt9X25JjUTDH8iyaRmVz89LOPgkYuBTGivxPxzu4=; b=DYGceVbb71RQfISwAIlVfjlYpXg2/yqHjxD0KPvWBvJO6QLdWFVl5kQiIlZK2cccan3F1x A6K07/UMLohSF/m7xRKWo2FSlA/lOStfE++jPgheoH9ZNglDAVN638E5Y7zG70DZFMuftL ++5Hw/16bjcl5Ptt7XVUFUfQq5ZOY8c= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 22 Nov 2019 14:46:57 +0000 Message-Id: <20191122144702.3780548-11-berrange@redhat.com> In-Reply-To: <20191122144702.3780548-1-berrange@redhat.com> References: <20191122144702.3780548-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 10/15] docs: convert kbase/launch_security_sev.html.in to RST X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: JCsGmg1hODWuhUiRHrQGrA-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) This is a semi-automated conversion. The first conversion is done using "pandoc -f html -t rst". The result is then editted manually to apply the desired heading markup, and fix a few things that pandoc gets wrong. Signed-off-by: Daniel P. Berrang=C3=A9 --- docs/kbase/launch_security_sev.html.in | 533 ------------------------- docs/kbase/launch_security_sev.rst | 529 ++++++++++++++++++++++++ 2 files changed, 529 insertions(+), 533 deletions(-) delete mode 100644 docs/kbase/launch_security_sev.html.in create mode 100644 docs/kbase/launch_security_sev.rst diff --git a/docs/kbase/launch_security_sev.html.in b/docs/kbase/launch_sec= urity_sev.html.in deleted file mode 100644 index 985c11a47b..0000000000 --- a/docs/kbase/launch_security_sev.html.in +++ /dev/null @@ -1,533 +0,0 @@ - - - - -

Launch security with AMD SEV

- -
    - -

    - Storage encryption in modern public cloud computing is a common pr= actice. - 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. -

    - -

    AMD SEV

    -

    - SEV (Secure Encrypted Virtualization) is a feature extension of AM= D's SME (Secure - Memory Encryption) intended for KVM virtual machines which is supp= orted - primarily on AMD's EPYC CPU line. In contrast to SME, SEV uses a u= nique memory encryption - key for each VM. The whole encryption of memory pages is completel= y transparent - to the hypervisor and happens inside dedicated hardware in the on-= die memory controller. - Each controller includes a high-performance Advanced Encryption St= andard - (AES) engine that encrypts data when it is written to DRAM and dec= rypts it - when read. - - For more details about the technology itself, you can visit - AMD's developer portal. -

    - -

    Enabling SEV on the host

    -

    - 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: -

    - -
    -$ cat /proc/cpuinfo | grep sev
    -...
    -sme ssbd sev ibpb
    - -

    - 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 li= ne: -

    - -
    -mem_encrypt=3Don kvm_amd.sev=3D1
    -      
    - -

    - To make the changes persistent, append the above to the variable= holding - parameters of the kernel command line in - /etc/default/grub to preserve SEV settings across r= eboots -

    - -
    -$ cat /etc/default/grub
    -...
    -GRUB_CMDLINE_LINUX=3D"... mem_encrypt=3Don kvm_amd.sev=3D1"
    -$ grub2-mkconfig -o /boot/efi/EFI/<distro>/grub.cfg
    - -

    - mem_encrypt=3Don turns on the SME memory encryption f= eature on - the host which protects against the physical attack on the hypervi= sor - memory. The kvm_amd.sev parameter actually enables SE= V in - the kvm module. It can be set on the command line alongside - mem_encrypt like shown above, or it can be put into a - module config under /etc/modprobe.d/ -

    - -
    -$ cat /etc/modprobe.d/sev.conf
    -options kvm_amd sev=3D1
    -      
    - -

    - After rebooting the host, you should see SEV being enabled in th= e kernel: -

    - -
    -$ cat /sys/module/kvm_amd/parameters/sev
    -1
    -      
    - -

    Checking SEV support in the virt stack

    -

    - Note: All of the commands bellow need to be run with root privi= leges. -

    - -

    - First make sure you have the following packages in the specified= versions: -

    - -
      -
    • - libvirt >=3D 4.5.0 (>5.1.0 recommended due to additional SEV b= ugfixes) -
    • -
    • - QEMU >=3D 2.12.0 -
    • -
    -

    - To confirm that the virtualization stack supports SEV, run the f= ollowing: -

    - -
    -# virsh domcapabilities
    -<domainCapabilities>
    -...
    -  <features>
    -    ...
    -    <sev supported=3D'yes'>
    -      <cbitpos>47</cbitpos>
    -      <reducedPhysBits>1</reducedPhysBits>
    -    </sev>
    -    ...
    -  </features>
    -</domainCapabilities>
    -

    - Note that if libvirt was already installed and libvirtd running = before enabling SEV in the kernel followed by the host reboot you need to f= orce libvirtd - to re-probe both the host and QEMU capabilities. First stop libv= irtd: -

    - -
    -# systemctl stop libvirtd.service
    -      
    - -

    - Now you need to clean the capabilities cache: -

    - -
    -# rm -f /var/cache/libvirt/qemu/capabilities/*
    -      
    - -

    - If you now restart libvirtd, it will re-probe the capabilities a= nd if - you now run: -

    - -
    -# virsh domcapabilities
    -      
    - -

    - SEV should be listed as supported. If you still see: -

    - -
    -<sev supported=3D'no'/>
    -      
    - -

    - it means one of two things: -

      -
    1. - libvirt does support SEV, but either QEMU or the host does n= ot -
    2. -
    3. - you have libvirt <=3D5.1.0 which suffered from getting a - 'Permission denied' on /dev/sev beca= use - of the default permissions on the character device which preve= nted - QEMU from opening it during capabilities probing - you can eit= her - manually tweak the permissions so that QEMU has access to it or - preferably install libvirt 5.1.0 or higher -
    4. -
    -

    - -

    VM Configuration

    -

    - SEV is enabled in the XML by specifying the - <= ;launchSecurity> element. However, specifying launchSecurity<= /code> isn't - enough to boot an SEV VM. Further configuration requirements are d= iscussed - below. -

    - -

    Machine type

    -

    - 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 t= ype is - strongly discouraged, since depending on how your OVMF package w= as - built (e.g. including features like SecureBoot or SMM) Q35 may e= ven be - required. -

    - -
    Q35
    -
    -...
    -<os>
    -  <type arch=3D'x86_64' machine=3D'pc-q35-3.0'>hvm</type>
    -  ...
    -</os>
    -...
    - -
    i440fx (discouraged)
    -
    -...
    -<os>
    -  <type arch=3D'x86_64' machine=3D'pc-i440fx-3.0'>hvm</type>
    -  ...
    -</os>
    -...
    -      
    - -

    Boot loader

    -

    - SEV is only going to work with OVMF (UEFI), so you'll need to po= int libvirt to - the correct OVMF binary. -

    -
    -...
    -<os>
    -  <type arch=3D'x86_64' machine=3D'pc-q35-3.0'>hvm</type>
    -  <loader readonly=3D'yes' type=3D'pflash'>/usr/share/edk2/ovmf/OVMF=
    _CODE.fd</loader>
    -</os>
    -...
    - -

    Memory

    -

    - 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 allocat= ed by QEMU - itself (UEFI pflash, device ROMs, video RAM, etc.) have to be en= crypted 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 cg= roup 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 fo= r the VM given - by <currentMemory> element. However, trying t= o account for the additional - memory regions QEMU allocates when calculating the limit in an a= utomated manner - is non-deterministic. One way to resolve this is to set the hard= limit manually. - -

    - 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 sh= ould suffice for - most workloads and may serve as a good starting point. - - For example, a domain with 4GB memory with a 256MiB extra hard l= imit would look - like this: -

    -

    - -
    -# virsh edit <domain>
    -<domain>
    -  ...
    -  <currentMemory unit=3D'KiB'>4194304</currentMemory>
    -  <memtune>
    -    <hard_limit unit=3D'KiB'>4456448</hard_limit>
    -  </memtune>
    -  ...
    -</domain>
    -

    - There's another, preferred method of taking care of the limits by - using the<memoryBacking> element along with t= he - <locked/> subelement: -

    - -
    -<domain>
    -  ...
    -  <memoryBacking>
    -    <locked/>
    -  </memoryBacking>
    -  ...
    -</domain>
    - -

    - What that does is that it tells libvirt not to force any hard li= mit (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. How= ever, 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 locki= ng all of the - host's available memory. The way to avoid this issue and to prot= ect the host is - to enforce a bigger hard limit on the master cgroup containing a= ll of the VMs - - on systemd this is machine.slice. -

    - -
    -# systemctl set-property machine.slice MemoryHigh=3D<value>
    - -

    - To put even stricter measures in place which would involve the O= OM killer, use -

    -# systemctl set-property machine.slice MemoryMax=3D<value>
    - instead. Alternatively, you can create a systemd config (don't f= orget - to reload systemd configuration in this case): -
    -# cat << EOF > /etc/systemd/system.control/machine.slice.d/90-Mem=
    oryMax.conf
    -MemoryMax=3D<value>
    -EOF
    - The trade-off to keep in mind with the second approach is that t= he VMs - can still perform DoS on each other. -

    - -

    Virtio

    -

    - In order to make virtio devices work, we need to enable emulated= IOMMU - on the devices so that virtual DMA can work. -

    - -
    -# virsh edit <domain>
    -<domain>
    -  ...
    -  <controller type=3D'virtio-serial' index=3D'0'>
    -    <driver iommu=3D'on'/>
    -  </controller>
    -  <controller type=3D'scsi' index=3D'0' model=3D'virtio-scsi'>
    -    <driver iommu=3D'on'/>
    -  </controller>
    -  ...
    -  <memballoon model=3D'virtio'>
    -    <driver iommu=3D'on'/>
    -  </memballoon>
    -  <rng model=3D'virtio'>
    -    <backend model=3D'random'>/dev/urandom</backend>
    -    <driver iommu=3D'on'/>
    -  </rng>
    -  ...
    -<domain>
    - -

    - If you for some reason want to use the legacy PC machine type, fur= ther changes - to the virtio - configuration is required, because SEV will not work with Virtio &= lt;1.0. In - libvirt, this is handled by using the virtio-non-transitional devi= ce model - (libvirt >=3D 5.2.0 required). - -

    - Note: some devices like video devices don't - support non-transitional model, which means that virtio GPU cann= ot be used. -

    -

    - -
    -<domain>
    -  ...
    -  <devices>
    -    ...
    -    <memballoon model=3D'virtio-non-transitional'>
    -      <driver iommu=3D'on'/>
    -    </memballoon>
    -  </devices>
    -  ...
    -</domain>
    - -

    Checking SEV from within the guest

    -

    - After making the necessary adjustments discussed in - Configuration, the VM should now bo= ot - successfully with SEV enabled. You can then verify that the guest = has - SEV enabled by running: -

    - -
    -# dmesg | grep -i sev
    -AMD Secure Encrypted Virtualization (SEV) active
    - -

    Limitations

    -

    - Currently, the boot disk cannot be of type virtio-blk, instead, vi= rtio-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 wri= ting the - article is 5.0.14). - If you still cannot start an SEV VM, it could be because of wrong = SELinux label on the /dev/sev 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 allo= w svirt_t to access the device (see audit2allow on how to do t= hat) or putting SELinux into permissive mode (discouraged). -

    - -

    Full domain XML examples

    - -
    Q35 machine
    -
    -<domain type=3D'kvm'>
    -  <name>sev-dummy</name>
    -  <memory unit=3D'KiB'>4194304</memory>
    -  <currentMemory unit=3D'KiB'>4194304</currentMemory>
    -  <memoryBacking>
    -    <locked/>
    -  </memoryBacking>
    -  <vcpu placement=3D'static'>4</vcpu>
    -  <os>
    -    <type arch=3D'x86_64' machine=3D'pc-q35-3.0'>hvm</type>
    -    <loader readonly=3D'yes' type=3D'pflash'>/usr/share/edk2/ovmf/OV=
    MF_CODE.fd</loader>
    -    <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram&g=
    t;
    -  </os>
    -  <features>
    -    <acpi/>
    -    <apic/>
    -    <vmport state=3D'off'/>
    -  </features>
    -  <cpu mode=3D'host-model' check=3D'partial'>
    -    <model fallback=3D'allow'/>
    -  </cpu>
    -  <clock offset=3D'utc'>
    -    <timer name=3D'rtc' tickpolicy=3D'catchup'/>
    -    <timer name=3D'pit' tickpolicy=3D'delay'/>
    -    <timer name=3D'hpet' present=3D'no'/>
    -  </clock>
    -  <on_poweroff>destroy</on_poweroff>
    -  <on_reboot>restart</on_reboot>
    -  <on_crash>destroy</on_crash>
    -  <pm>
    -    <suspend-to-mem enabled=3D'no'/>
    -    <suspend-to-disk enabled=3D'no'/>
    -  </pm>
    -  <devices>
    -    <emulator>/usr/bin/qemu-kvm</emulator>
    -    <disk type=3D'file' device=3D'disk'>
    -      <driver name=3D'qemu' type=3D'qcow2'/>
    -      <source file=3D'/var/lib/libvirt/images/sev-dummy.qcow2'/>
    -      <target dev=3D'sda' bus=3D'scsi'/>
    -      <boot order=3D'1'/>
    -    </disk>
    -    <controller type=3D'virtio-serial' index=3D'0'>
    -      <driver iommu=3D'on'/>
    -    </controller>
    -    <controller type=3D'scsi' index=3D'0' model=3D'virtio-scsi'>
    -      <driver iommu=3D'on'/>
    -    </controller>
    -    <interface type=3D'network'>
    -      <mac address=3D'52:54:00:cc:56:90'/>
    -      <source network=3D'default'/>
    -      <model type=3D'virtio'/>
    -      <driver iommu=3D'on'/>
    -    </interface>
    -    <graphics type=3D'spice' autoport=3D'yes'>
    -      <listen type=3D'address'/>
    -      <gl enable=3D'no'/>
    -    </graphics>
    -    <video>
    -      <model type=3D'qxl'/>
    -    </video>
    -    <memballoon model=3D'virtio'>
    -      <driver iommu=3D'on'/>
    -    </memballoon>
    -    <rng model=3D'virtio'>
    -      <driver iommu=3D'on'/>
    -    </rng>
    -  </devices>
    -  <launchSecurity type=3D'sev'>
    -    <cbitpos>47</cbitpos>
    -    <reducedPhysBits>1</reducedPhysBits>
    -    <policy>0x0003</policy>
    -  </launchSecurity>
    -</domain>
    - -
    PC-i440fx machine:
    -
    -<domain type=3D'kvm'>
    -  <name>sev-dummy-legacy</name>
    -  <memory unit=3D'KiB'>4194304</memory>
    -  <currentMemory unit=3D'KiB'>4194304</currentMemory>
    -  <memtune>
    -    <hard_limit unit=3D'KiB'>5242880</hard_limit>
    -  </memtune>
    -  <vcpu placement=3D'static'>4</vcpu>
    -  <os>
    -    <type arch=3D'x86_64' machine=3D'pc-i440fx-3.0'>hvm</type>
    -    <loader readonly=3D'yes' type=3D'pflash'>/usr/share/edk2/ovmf/OV=
    MF_CODE.fd</loader>
    -    <nvram>/var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd</nvram&g=
    t;
    -    <boot dev=3D'hd'/>
    -  </os>
    -  <features>
    -  <acpi/>
    -  <apic/>
    -  <vmport state=3D'off'/>
    -  </features>
    -  <cpu mode=3D'host-model' check=3D'partial'>
    -    <model fallback=3D'allow'/>
    -  </cpu>
    -  <clock offset=3D'utc'>
    -    <timer name=3D'rtc' tickpolicy=3D'catchup'/>
    -    <timer name=3D'pit' tickpolicy=3D'delay'/>
    -    <timer name=3D'hpet' present=3D'no'/>
    -  </clock>
    -  <on_poweroff>destroy</on_poweroff>
    -  <on_reboot>restart</on_reboot>
    -  <on_crash>destroy</on_crash>
    -  <pm>
    -    <suspend-to-mem enabled=3D'no'/>
    -    <suspend-to-disk enabled=3D'no'/>
    -  </pm>
    -  <devices>
    -    <emulator>/usr/bin/qemu-kvm</emulator>
    -    <disk type=3D'file' device=3D'disk'>
    -      <driver name=3D'qemu' type=3D'qcow2'/>
    -      <source file=3D'/var/lib/libvirt/images/sev-dummy-seabios.qcow2'/=
    >
    -      <target dev=3D'sda' bus=3D'sata'/>
    -    </disk>
    -    <interface type=3D'network'>
    -      <mac address=3D'52:54:00:d8:96:c8'/>
    -      <source network=3D'default'/>
    -      <model type=3D'virtio-non-transitional'/>
    -    </interface>
    -    <serial type=3D'pty'>
    -      <target type=3D'isa-serial' port=3D'0'>
    -        <model name=3D'isa-serial'/>
    -      </target>
    -    </serial>
    -    <console type=3D'pty'>
    -      <target type=3D'serial' port=3D'0'/>
    -    </console>
    -    <input type=3D'tablet' bus=3D'usb'>
    -      <address type=3D'usb' bus=3D'0' port=3D'1'/>
    -    </input>
    -    <input type=3D'mouse' bus=3D'ps2'/>
    -    <input type=3D'keyboard' bus=3D'ps2'/>
    -    <graphics type=3D'spice' autoport=3D'yes'>
    -      <listen type=3D'address'/>
    -      <gl enable=3D'no'/>
    -    </graphics>
    -    <video>
    -      <model type=3D'qxl' ram=3D'65536' vram=3D'65536' vgamem=3D'16384'=
     heads=3D'1' primary=3D'yes'/>
    -    </video>
    -    <memballoon model=3D'virtio-non-transitional'>
    -      <driver iommu=3D'on'/>
    -    </memballoon>
    -      <rng model=3D'virtio-non-transitional'>
    -    <driver iommu=3D'on'/>
    -    </rng>
    -  </devices>
    -  <launchSecurity type=3D'sev'>
    -    <cbitpos>47</cbitpos>
    -    <reducedPhysBits>1</reducedPhysBits>
    -    <policy>0x0003</policy>
    -  </launchSecurity>
    -</domain>
    - - diff --git a/docs/kbase/launch_security_sev.rst b/docs/kbase/launch_securit= y_sev.rst new file mode 100644 index 0000000000..4387ae64b0 --- /dev/null +++ b/docs/kbase/launch_security_sev.rst @@ -0,0 +1,529 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D +Launch security with AMD SEV +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +.. contents:: + +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. + +AMD SEV +=3D=3D=3D=3D=3D=3D=3D + +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 `AMD's developer portal `__. + +Enabling SEV on the host +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +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: + +:: + + $ cat /proc/cpuinfo | grep sev + ... + sme ssbd sev ibpb + +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: + +:: + + mem_encrypt=3Don kvm_amd.sev=3D1 + +To make the changes persistent, append the above to the variable holding +parameters of the kernel command line in ``/etc/default/grub`` to +preserve SEV settings across reboots + +:: + + $ cat /etc/default/grub + ... + GRUB_CMDLINE_LINUX=3D"... mem_encrypt=3Don kvm_amd.sev=3D1" + $ grub2-mkconfig -o /boot/efi/EFI//grub.cfg + +``mem_encrypt=3Don`` turns on the SME memory encryption feature on the +host which protects against the physical attack on the hypervisor +memory. The ``kvm_amd.sev`` parameter actually enables SEV in the kvm +module. It can be set on the command line alongside ``mem_encrypt`` like +shown above, or it can be put into a module config under +``/etc/modprobe.d/`` + +:: + + $ cat /etc/modprobe.d/sev.conf + options kvm_amd sev=3D1 + +After rebooting the host, you should see SEV being enabled in the +kernel: + +:: + + $ cat /sys/module/kvm_amd/parameters/sev + 1 + + +Checking SEV support in the virt stack +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +**Note: All of the commands bellow need to be run with root +privileges.** + +First make sure you have the following packages in the specified +versions: + +- libvirt >=3D 4.5.0 (>5.1.0 recommended due to additional SEV bugfixes) +- QEMU >=3D 2.12.0 + +To confirm that the virtualization stack supports SEV, run the +following: + +:: + + # virsh domcapabilities + + ... + + ... + + 47 + 1 + + ... + + + +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: + +:: + + # systemctl stop libvirtd.service + +Now you need to clean the capabilities cache: + +:: + + # rm -f /var/cache/libvirt/qemu/capabilities/* + +If you now restart libvirtd, it will re-probe the capabilities and if +you now run: + +:: + + # virsh domcapabilities + +SEV should be listed as supported. If you still see: + +:: + + + +it means one of two things: + +#. libvirt does support SEV, but either QEMU or the host does not +#. you have libvirt <=3D5.1.0 which suffered from getting a + ``'Permission denied'`` on ``/dev/sev`` 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 + +VM Configuration +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +SEV is enabled in the XML by specifying the +` `__ +element. However, specifying ``launchSecurity`` isn't enough to boot an +SEV VM. Further configuration requirements are discussed below. + +Machine type +------------ + +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. + +Q35 +~~~ + +:: + + ... + + hvm + ... + + ... + +i440fx (discouraged) +~~~~~~~~~~~~~~~~~~~~ + +:: + + ... + + hvm + ... + + ... + +Boot loader +----------- + +SEV is only going to work with OVMF (UEFI), so you'll need to point +libvirt to the correct OVMF binary. + +:: + + ... + + hvm + /usr/share/edk2/ovmf/OVMF_CO= DE.fd + + ... + +Memory +------ + +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 +```` 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. + +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: + +:: + + # virsh edit + + ... + 4194304 + + 4456448 + + ... + + +There's another, preferred method of taking care of the limits by using +the\ ```` element along with the ```` +subelement: + +:: + + + ... + + + + ... + + +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 ``machine.slice``. + +:: + + # systemctl set-property machine.slice MemoryHigh=3D + +To put even stricter measures in place which would involve the OOM +killer, use + +:: + + # systemctl set-property machine.slice MemoryMax=3D + +instead. Alternatively, you can create a systemd config (don't forget to +reload systemd configuration in this case): + +:: + + # cat << EOF > /etc/systemd/system.control/machine.slice.d/90-MemoryMax= .conf + MemoryMax=3D + EOF + +The trade-off to keep in mind with the second approach is that the VMs +can still perform DoS on each other. + +Virtio +------ + +In order to make virtio devices work, we need to enable emulated IOMMU +on the devices so that virtual DMA can work. + +:: + + # virsh edit + + ... + + + + + + + ... + + + + + /dev/urandom + + + ... + + +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 >=3D 5.2.0 required). + +Note: some devices like video devices don't support non-transitional +model, which means that virtio GPU cannot be used. + +:: + + + ... + + ... + + + + + ... + + +Checking SEV from within the guest +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +After making the necessary adjustments discussed in +`Configuration <#Configuration>`__, the VM should now boot successfully +with SEV enabled. You can then verify that the guest has SEV enabled by +running: + +:: + + # dmesg | grep -i sev + AMD Secure Encrypted Virtualization (SEV) active + +Limitations +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +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 ``/dev/sev`` +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 +``audit2allow`` on how to do that) or putting SELinux into permissive +mode (discouraged). + +Full domain XML examples +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Q35 machine +----------- + +:: + + + sev-dummy + 4194304 + 4194304 + + + + 4 + + hvm + /usr/share/edk2/ovmf/OVMF_= CODE.fd + /var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd + + + + + + + + + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-kvm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 47 + 1 + 0x0003 + + + +PC-i440fx machine +----------------- + +:: + + + sev-dummy-legacy + 4194304 + 4194304 + + 5242880 + + 4 + + hvm + /usr/share/edk2/ovmf/OVMF_= CODE.fd + /var/lib/libvirt/qemu/nvram/sev-dummy_VARS.fd + + + + + + + + + + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-kvm + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + 47 + 1 + 0x0003 + + --=20 2.23.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list