Chapter 15. Securing virtual machines
As an administrator of a RHEL 8 system with virtual machines (VMs), ensuring that your VMs are as secure as possible significantly lowers the risk of your guest and host OSs being infected by malicious software.
This document outlines the mechanics of securing VMs on a RHEL 8 host and provides a list of methods to increase the security of your VMs.
15.1. How security works in virtual machines
When using virtual machines (VMs), multiple operating systems can be housed within a single host machine. These systems are connected with the host through the hypervisor, and usually also through a virtual network. As a consequence, each VM can be used as a vector for attacking the host with malicious software, and the host can be used as a vector for attacking any of the VMs.
Figure 15.1. A potential malware attack vector on a virtualization host

Because the hypervisor uses the host kernel to manage VMs, services running on the VM’s operating system are frequently used for injecting malicious code into the host system. However, you can protect your system against such security threats by using a number of security features on your host and your guest systems.
These features, such as SELinux or QEMU sandboxing, provide various measures that make it more difficult for malicious code to attack the hypervisor and transfer between your host and your VMs.
Figure 15.2. Prevented malware attacks on a virtualization host

Many of the features that RHEL 8 provides for VM security are always active and do not have to be enabled or configured. For details, see Section 15.4, “Automatic features for virtual machine security”.
In addition, you can adhere to a variety of best practices to minimize the vulnerability of your VMs and your hypervisor. For more information, see Section 15.2, “Best practices for securing virtual machines”.
15.2. Best practices for securing virtual machines
Following the instructions below significantly decreases the risk of your virtual machines being infected with malicious code and used as attack vectors to infect your host system.
On the guest side:
Secure the virtual machine as if it was a physical machine. The specific methods available to enhance security depend on the guest OS.
If your VM is running RHEL 8, see Configuring and managing security in RHEL 8 for detailed instructions on improving the security of your guest system.
On the host side:
- When managing VMs remotely, use cryptographic utilities such as SSH and network protocols such as SSL for connecting to the VMs.
Ensure SELinux is in Enforcing mode:
# getenforce Enforcing
If SELinux is disabled or in Permissive mode, see the Using SELinux document for instructions on activating Enforcing mode.
NoteSELinux Enforcing mode also enables the sVirt RHEL 8 feature. This is a set of specialized SELinux booleans for virtualization, which can be manually adjusted for fine-grained VM security management.
Use VMs with SecureBoot:
SecureBoot is a feature that ensures that your VM is running a cryptographically signed OS. This prevents VMs whose OS has been altered by a malware attack from booting.
SecureBoot can only be applied when installing a Linux VM that uses OVMF firmware. For instructions, see Section 15.3, “Creating a SecureBoot virtual machine”.
Do not use
qemu-*
commands, such asqemu-img
.QEMU is an essential component of the virtualization architecture in RHEL 8, but it is difficult to manage manually, and improper QEMU configurations may cause security vulnerabilities. Therefore, using
qemu-*
commands is not supported by Red Hat. Instead, it is highly recommended to interact with QEMU using libvirt utilities, such asvirsh
,virt-install
, andvirt-xml
, as these orchestrate QEMU according to the best practices.
Additional resources
- For detailed information on modifying your virtualization booleans, see Section 15.5, “Virtualization booleans”.
15.3. Creating a SecureBoot virtual machine
The following provides instructions on creating a Linux virtual machine (VM) that uses the SecureBoot feature, which ensures that your VM is running a cryptographically signed OS. If the guest OS of a VM has been altered by malware, SecureBoot prevents the VM from booting, which stops the potential spread of the malware to your host machine.
Prerequisites
- The VM is using the Q35 machine type.
The
edk2-OVMF
packages is installed:# yum install edk2-ovmf
An operating system (OS) installation source is available locally or on a network. This can be one of the following formats:
- An ISO image of an installation medium
- A disk image of an existing VM installation
- Optional: A Kickstart file can be provided for faster and easier configuration of the installation.
Procedure
Use the
virt-install
command to create a VM as detailed in Section 2.2.1, “Creating virtual machines using the command-line interface”. For the--boot
option, use theuefi,nvram_template=/usr/share/OVMF/OVMF_VARS.secboot.fd
value. This uses theOVMF_VARS.secboot.fd
andOVMF_CODE.secboot.fd
files as templates for the VM’s non-volatile RAM (NVRAM) settings, which enables the SecureBoot feature.For example:
# virt-install --name rhel8sb --memory 4096 --vcpus 4 --os-variant rhel8.0 --boot uefi,nvram_template=/usr/share/OVMF/OVMF_VARS.secboot.fd --disk boot_order=2,size=10 --disk boot_order=1,device=cdrom,bus=scsi,path=/images/RHEL-8.0-installation.iso
- Follow the OS installation procedure according to the instructions on the screen.
- After the guest OS is installed, access the VM’s command line by opening the terminal in the graphical guest console or connecting to the guest OS using SSH.
Verify that SecureBoot is enabled by using the
mokutil --sb-state
command:# mokutil --sb-state SecureBoot enabled
15.4. Automatic features for virtual machine security
In addition to manual means of improving the security of your virtual machines listed in Section 15.2, “Best practices for securing virtual machines”, a number of security features are provided by the libvirt software suite and are automatically enabled when using virtualization in RHEL 8. These include:
- System and user sessions
To access all the available utilities for virtual machine management in RHEL 8, you need to use the system session of libvirt. To do so, you must have root privileges on the system or be a part of the libvirt user group.
Non-root users that are not in the libvirt group can only access a user session of libvirt, which has to respect the access rights of the local user when accessing resources. For example, in the user session, you cannot detect or access VMs created in the system session or by other users. Also, available VM networking configuration options are significantly limited.
NoteThe RHEL 8 documentation assumes you have libvirt system session privileges.
- Virtual machine separation
- Individual VMs run as isolated processes on the host, and rely on security enforced by the host kernel. Therefore, a VM cannot read or access the memory or storage of other VMs on the same host.
- QEMU sandboxing
- A feature that prevents QEMU code from executing system calls that can compromise the security of the host.
- Kernel Address Space Randomization (KASLR)
- Enables randomizing the physical and virtual addresses at which the kernel image is decompressed. Thus, KASLR prevents guest security exploits based on the location of kernel objects.
15.5. Virtualization booleans
For fine-grained configuration of virtual machines security on a RHEL 8 system, you can configure SELinux booleans on the host to ensure the hypervisor acts in a specific way.
To list all virtualization-related booleans and their statuses, use the getsebool -a | grep virt
command:
$ getsebool -a | grep virt
[...]
virt_sandbox_use_netlink --> off
virt_sandbox_use_sys_admin --> off
virt_transition_userdomain --> off
virt_use_comm --> off
virt_use_execmem --> off
virt_use_fusefs --> off
[...]
To enable a specific boolean, use the setsebool -P boolean_name on
command as root. To disable a boolean, use setsebool -P boolean_name off
.
The following table lists virtualization-related booleans available in RHEL 8 and what they do when enabled:
Table 15.1. SELinux virtualization booleans
SELinux Boolean | Description |
---|---|
staff_use_svirt | Enables non-root users to create and transition VMs to sVirt. |
unprivuser_use_svirt | Enables unprivileged users to create and transition VMs to sVirt. |
virt_sandbox_use_audit | Enables sandbox containers to send audit messages. |
virt_sandbox_use_netlink | Enables sandbox containers to use netlink system calls. |
virt_sandbox_use_sys_admin | Enables sandbox containers to use sys_admin system calls, such as mount. |
virt_transition_userdomain | Enables virtual processes to run as user domains. |
virt_use_comm | Enables virt to use serial/parallel communication ports. |
virt_use_execmem | Enables confined virtual guests to use executable memory and executable stack. |
virt_use_fusefs | Enables virt to read FUSE mounted files. |
virt_use_nfs | Enables virt to manage NFS mounted files. |
virt_use_rawip | Enables virt to interact with rawip sockets. |
virt_use_samba | Enables virt to manage CIFS mounted files. |
virt_use_sanlock | Enables confined virtual guests to interact with the sanlock. |
virt_use_usb | Enables virt to use USB devices. |
virt_use_xserver | Enables virtual machine to interact with the X Window System. |
15.6. Setting up IBM Secure Execution on IBM Z
When using IBM Z hardware to run a RHEL 8 host, you can improve the security of your virtual machines (VMs) by configuring IBM Secure Execution for the VMs.
IBM Secure Execution, also known as Protected Virtualization, prevents the host system from accessing a VM’s state and memory contents. As a result, even if the host is compromised, it cannot be used as a vector for attacking the guest operating system. In addition, Secure Execution can be used to prevent untrusted hosts from obtaining sensitive information from the VM.
The following procedure describes how to convert an existing VM on an IBM Z host into a secured VM.
Prerequisites
The system hardware is one of the following:
- IBM z15 or later
- IBM LinuxONE III or later
The Secure Execution feature is enabled for your system. To verify, use:
# grep facilities /proc/cpuinfo | grep 158
If this command displays any output, your CPU is compatible with Secure Execution.
The kernel includes support for Secure Execution. To confirm, use:
# ls /sys/firmware | grep uv
If the command generates any output, your kernel supports Secure Execution.
The host CPU model contains the
unpack
facility. To confirm, use:# virsh domcapabilities | grep unpack <feature policy='require' name='unpack'/>
If the command generates the above output, your CPU host model is compatible with Secure Execution.
The CPU mode of the VM is set to
host-model
. To confirm this, use the following and replacevm-name
with the name of your VM.# virsh dumpxml vm-name | grep "<cpu mode='host-model'/>"
If the command generates any output, the VM’s CPU mode is set correctly.
- You have obtained and verified the IBM Z host key document. For instructions to do so, see Verifying the host key document in IBM documentation.
Procedure
Add the
prot_virt=1
kernel parameter to the boot configuration of the host.# # grubby --update-kernel=ALL --args="prot_virt=1"
Create a parameter file for the VM you want to secure. For example:
# touch ~/secure-parameters
In the
/boot/loader/entries
directory of the host, identify the boot loader entry with the latest version:# ls /boot/loader/entries -l [...] -rw-r--r--. 1 root root 281 Oct 9 15:51 3ab27a195c2849429927b00679db15c1-4.18.0-240.el8.s390x.conf
Retrieve the kernel options line of the boot loader entry:
# cat /boot/loader/entries/3ab27a195c2849429927b00679db15c1-4.18.0-240.el8.s390x.conf | grep options options root=/dev/mapper/rhel-root crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap
Add the content of the options line and
swiotlb=262144
to the created parameters file.# echo "root=/dev/mapper/rhel-root crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap swiotlb=262144" > ~/secure-parameters
Generate an IBM Secure Execution image for the selected VM.
For example, the following creates a
/boot/secure-image
secured image based on the/boot/vmlinuz-4.18.0-240.el8.s390x
image, using thesecure-parameters
file, the/boot/initramfs-4.18.0-240.el8.s390x.img
initial RAM disk file, and theHKD-8651-000201C048.crt
host key document.# genprotimg -i /boot/vmlinuz-4.18.0-240.el8.s390x -r /boot/initramfs-4.18.0-240.el8.s390x.img -p ~/secure-parameters -k HKD-8651-00020089A8.crt -o /boot/secure-image
Using the
genprotimg
utility creates the secure image, which contains the kernel parameters, initial RAM disk, and boot image.In the guest operating system of the VM, update the VM’s boot menu to boot from the secure image. In addition, remove the lines starting with
initrd
andoptions
, as they are not needed.For example, in a RHEL 8.3 VM, the boot menu can be edited in the
/boot/loader/entries/
directory:# cat /boot/loader/entries/3ab27a195c2849429927b00679db15c1-4.18.0-240.el8.s390x.conf title Red Hat Enterprise Linux 8.3 version 4.18.0-240.el8.s390x linux /boot/secure-image [...]
Enable virtio devices to use shared buffers. To do so, use
virsh edit
to modify the XML configuration of the VM, and addiommu='on'
to the<driver>
line of all devices that have one. For example:<interface type='network'> <source network='default'/> <model type='virtio'/> <driver name='vhost' iommu='on'/> </interface>
If a device configuration does not contain any
<driver>
line, add<driver iommu='on'\>
instead.Disable memory ballooning on the VM, as the feature is not compatible with Secure Execution. To do so, add the following line to the VM’s XML configuration.
<memballoon model='none'/>
Create the bootable disk image
# zipl -V
Securely remove the original unprotected files. For example:
# shred /boot/vmlinuz-4.18.0-240.el8.s390x # shred /boot/initramfs-4.18.0-240.el8.s390x.img # shred secure-parameters
The original boot image, the initial RAM image, and the kernel parameter file are unprotected, and if they are not removed, VMs with Secure Execution enabled can still be vulnerable to hacking attempts or sensitive data mining.
Verification
On the host, use the
virsh dumpxml
utility to confirm the XML configuration of the secured VM. The configuration must include the<driver iommu='on'/>
and<memballoon model='none'/>
elements.# virsh dumpxml vm-name [...] <cpu mode='host-model'/> <devices> <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none' io='native' iommu='on'> <source file='/var/lib/libvirt/images/secure-guest.qcow2'/> <target dev='vda' bus='virtio'/> </disk> <interface type='network'> <driver iommu='on'/> <source network='default'/> <model type='virtio'/> </interface> <console type='pty'/> <memballoon model='none'/> </devices> </domain>
Additional resources
- For additonal instructions on modifying the boot configuration of the host, see Configuring kernel command-line parameters.
-
For more information on the
genprotimg
utility, see IBM documentation.
15.7. Attaching cryptographic coprocessors to virtual machines on IBM Z
To use hardware encryption in your virtual machine (VM) on an IBM Z host, create mediated devices from a cryptographic coprocessor device and assign them to the intended VMs. For detailed instructions, see below.
Prerequisites
- Your host is running on IBM Z hardware.
The cryptographic coprocessor is compatible with device assignment. To confirm this, ensure that the
type
of your coprocessor is listed asCEX4
or later.# lszcrypt -V CARD.DOMAIN TYPE MODE STATUS REQUESTS PENDING HWTYPE QDEPTH FUNCTIONS DRIVER -------------------------------------------------------------------------------------------- 05 CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4card 05.0004 CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4queue 05.00ab CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4queue
- The mdevctl package is installed.
The
vfio_ap
kernel module is loaded. To verify, use:# lsmod | grep vfio_ap vfio_ap 24576 0 [...]
To load the module, use:
# modprobe vfio_ap
Procedure
On the host, reassign your crypto device to the
vfio-ap
drivers. The following example assigns two crypto devices with bitmask IDs(0x05, 0x0004)
and(0x05, 0x00ab)
tovfio-ap
.# echo -0x05 > /sys/bus/ap/apmask # echo -0x0004, -0x00ab > /sys/bus/ap/aqmask
For information on identifying the bitmask ID values, see Preparing pass-through devices for cryptographic adapter resources in the KVM Virtual Server Management document from IBM.
Verify that the crypto devices have been reassigned correctly.
# lszcrypt -V CARD.DOMAIN TYPE MODE STATUS REQUESTS PENDING HWTYPE QDEPTH FUNCTIONS DRIVER -------------------------------------------------------------------------------------------- 05 CEX5C CCA-Coproc - 1 0 11 08 S--D--N-- cex4card 05.0004 CEX5C CCA-Coproc - 1 0 11 08 S--D--N-- vfio_ap 05.00ab CEX5C CCA-Coproc - 1 0 11 08 S--D--N-- vfio_ap
If the DRIVER values of the domain queues changed to
vfio_ap
, the reassignment succeeded.Generate a device UUID.
# uuidgen 669d9b23-fe1b-4ecb-be08-a2fabca99b71
In the following steps of this procedure, replace
669d9b23-fe1b-4ecb-be08-a2fabca99b71
with your generated UUID.Using the UUID, create a new
vfio_ap
device.The following example shows creating a persistent mediated device and assigning queues to it. For example, the following commands assign domain adapter
0x05
and domain queues0x0004
and0x00ab
to device669d9b23-fe1b-4ecb-be08-a2fabca99b71
.# mdevctl define --uuid 669d9b23-fe1b-4ecb-be08-a2fabca99b71 --parent matrix --type vfio_ap-passthrough # mdevctl modify --uuid 669d9b23-fe1b-4ecb-be08-a2fabca99b71 --addattr=assign_adapter --value=0x05 # mdevctl modify --uuid 669d9b23-fe1b-4ecb-be08-a2fabca99b71 --addattr=assign_domain --value=0x0004 # mdevctl modify --uuid 669d9b23-fe1b-4ecb-be08-a2fabca99b71 --addattr=assign_domain --value=0x00ab
Start the mediated device.
# mdevctl start --uuid 669d9b23-fe1b-4ecb-be08-a2fabca99b71
Check that the configuration has been applied correctly
# cat /sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough/devices/669d9b23-fe1b-4ecb-be08-a2fabca99b71 05.0004 05.00ab
If the output contains the numerical values of queues that you have previously assigned to
vfio-ap
, the process was successful.Use the
virsh edit
command to open the XML configuration of the VM where you want to use the crypto devices.# virsh edit vm-name
Add the following lines to the
<devices>
section in the XML configuration, and save it.<hostdev mode='subsystem' type='mdev' managed='no' model='vfio-ap'> <source> <address uuid='669d9b23-fe1b-4ecb-be08-a2fabca99b71'/> </source> </hostdev>
Note that each UUID can only be assigned to one VM at a time.
Verification
- Start the VM to which you assigned the mediated device.
After the guest operating system (OS) boots, ensure that it detects the assigned crypto devices.
# lszcrypt -V CARD.DOMAIN TYPE MODE STATUS REQUESTS PENDING HWTYPE QDEPTH FUNCTIONS DRIVER -------------------------------------------------------------------------------------------- 05 CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4card 05.0004 CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4queue 05.00ab CEX5C CCA-Coproc online 1 0 11 08 S--D--N-- cex4queue
The output of this command in the guest OS will be identical to that on a host logical partition with the same cryptographic coprocessor devices available.
15.8. Enabling standard hardware security on Windows virtual machines
To secure Windows virtual machines (VMs), you can enable basic level security using the standard hardware capabilities of the Windows device.
Prerequisites
- Make sure you have installed the latest WHQL certified VirtIO drivers.
- Make sure the VM’s firmware supports UEFI boot.
Install the
edk2-OVMF
package on your host machine.# yum install edk2-ovmf
Install the
vTPM
packages on your host machine.# yum install swtpm libtpms
- Make sure the VM is using the Q35 machine architecture.
- Make sure you have the Windows installation media.
Procedure
Enable TPM 2.0 by adding the following parameters to the
<devices>
section in the VM’s XML configuration.<devices> [...] <tpm model='tpm-crb'> <backend type='emulator' version='2.0'/> </tpm> [...] </devices>
- Install Windows in UEFI mode. For more information on how to do so, see Creating a SecureBoot virtual machine.
- Install the VirtIO drivers on the Windows VM. For more information on how to do so, see Installing virtio drivers on a Windows guest.
- In UEFI, enable Secure Boot. For more information on how to do so, see Secure Boot.
Verification
Ensure that the Device Security page on your Windows machine displays the following message:
Your device meets the requirements for standard hardware security.