Hide Forgot
Created attachment 1757309 [details] Sample reproducer Description of problem: BZ#1564270 added support for auto-negotiation of UEFI firmware using the firmware metadata files provided by QEMU. This allows us to specify the following as part of the XML generation: <os firmware="efi"> <type arch="x86_64" machine="pc-q35-5.1">hvm</type> <boot dev="cdrom"/> </os> Which libvirt will duly transform into e.g.: <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' secure='no' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd</loader> <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/home/user/.config/libvirt/qemu/nvram/alpinelinux-q35-uefi-experiment_VARS.fd</nvram> <boot dev='cdrom'/> </os> I'm attempting to boot a live CD to sanity check things. Upon booting, I see the following emitted: BdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00001 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0) BdsDxe: failed to load Boot0001 "UEFI QEMU DVD-ROM QM00001 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0): Access Denied BdsDxe: No bootable option or device was found. BdsDxe: Press any key to enter the Boot Manager Menu. This appears to be an issue with secure boot. I duly disabled this by adding the '<loader>' element, like so: <os firmware="efi"> <type arch="x86_64" machine="pc-q35-5.1">hvm</type> <loader secure="no"/> <boot dev="cdrom"/> </os> However, this still fails. Looking at the XML, it appears libvirt has ignored the '//os/loader[@secure]' attribute: <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' secure='no' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd</loader> <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/home/stephenfin/.config/libvirt/qemu/nvram/alpinelinux-q35-uefi-experiment_VARS.fd</nvram> <boot dev='cdrom'/> </os> If I manually specify the firmware, the issue goes away and I'm able to boot the live CD: <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <boot dev='cdrom'/> </os> Version-Release number of selected component (if applicable): libvirt 6.6.0 edk2-ovmf 20200801stable How reproducible: Always. Steps to Reproduce: Using the attached XML 1. cd /tmp 2. wget https://dl-cdn.alpinelinux.org/alpine/v3.13/releases/x86_64/alpine-virt-3.13.1-x86_64.iso 3. virsh create alpine-virt.xml 4. virsh console alpinelinux-q35-uefi-experiment Actual results: Bootloader is unable to boot from live CD. Expected results: Instance should boot. Additional info:
Some additional information: $ ls /usr/share/qemu/firmware/ -1 40-edk2-ovmf-x64-sb-enrolled.json 50-edk2-ovmf-x64-sb.json 60-edk2-ovmf-x64.json 70-edk2-aarch64-verbose.json
Another data point. This works: <os firmware="efi"> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <boot dev='cdrom'/> </os> It results in the following XML: <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <nvram>/home/stephenfin/.config/libvirt/qemu/nvram/alpinelinux-q35-uefi-experiment_VARS.fd</nvram> <boot dev='cdrom'/> </os> This does not work: <os firmware="efi"> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <boot dev='cdrom'/> </os> It results in the following XML, where we see the requested loader is totally ignored. This seems like it should be an error? <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd</loader> <nvram template='/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'>/home/stephenfin/.config/libvirt/qemu/nvram/alpinelinux-q35-uefi-experiment_VARS.fd</nvram> <boot dev='cdrom'/> </os> Also, I tried with a Fedora 33 Workstation image and things boot just fine regardless of the bootloader configuration. This is presumably because the Fedora images are signed? I've documented my findings at [1], though it mostly duplicates what I've already said here. [1] https://that.guru/blog/uefi-secure-boot-in-libvirt/
(In reply to Stephen Finucane from comment #3) > Another data point. This works: > > <os firmware="efi"> > <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> > <loader readonly='yes' > type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> > <boot dev='cdrom'/> > </os> Apologies. This should read: <os> <type arch='x86_64' machine='pc-q35-5.1'>hvm</type> <loader readonly='yes' type='pflash'>/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <boot dev='cdrom'/> </os> i.e. no 'firmware' attribute on the 'os' element. If the 'firmware' attribute is specified, everything else inside the '<os>' element is seemingly ignored, which seems wrong: surely this should raise an error rather than being silently dropped? I tried experimenting with the 'secure' attribute of the 'loader' element. For example: <os> <type arch="x86_64" machine="pc-q35-5.1">hvm</type> <loader readonly="yes" type="pflash" secure="no">/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd</loader> <boot dev="cdrom"/> </os> The docs [1] suggest setting the 'secure' attribute should allow me to control secure boot behavior, stating: Moreover, some firmwares may implement the Secure boot feature. Attribute secure can be used then to control it. This would also align with what I've been told me about secure boot-enabled firmware being able to be used for non-secure boot guests. However, secure boot still appears to be enabled and I'm unable to boot the guest, with the same Access Denied errors being raised by the bootloader. Note that doing the opposite and attempting to set the 'secure="yes"' attribute when using a non-secure boot firmware does fail as expected. For example: <os> <type arch="x86_64" machine="pc-q35-5.1">hvm</type> <loader readonly="yes" type="pflash" secure="yes">/usr/share/edk2/ovmf/OVMF_CODE.fd</loader> <boot dev="cdrom"/> </os> This fails with the following error message: error: Failed to create domain from alpine-test.xml error: unsupported configuration: Secure boot requires SMM feature enabled Finally, I have also tested this with a Mageia 7.1 netinstall image just to rule out issues with the Alpine Linux issue. This image was chosen as the Mageia docs suggest that UEFI is supported but secure boot is not [2]. Once again, I see an Access Denied error from the bootloader if the secboot firmware is used. [1] https://libvirt.org/formatdomain.html#bios-bootloader [2] https://wiki.mageia.org/en/About_EFI_UEFI#Secure_Boot
Hi, thanks for the report. The situation with secure boot and firmwares is a bit complicated. One thing to note is that there is no '/usr/share/edk2/ovmf/OVMF_CODE.fd' in RHEL-8, my guess is that you tried it on Fedora. There are several JSON descriptions of firmware configurations: 1) '40-edk2-ovmf-sb.json' (RHEL-8), '40-edk2-ovmf-x64-sb-enrolled.json' (Fedora-33) - secure boot feature enabled, keys enrolled - With this configuration it will boot only signed loaders, others are rejected with 'Access denied' or 'permission denied' so similar. - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd' and NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'. 2) '50-edk2-ovmf.json' (RHEL-8), '50-edk2-ovmf-x64-sb.json' (Fedora-33) - secure boot feature enabled, no keys enrolled - With this configuration it will boot all loaders because there are no keys to verify any signature. - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd' and NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.fd'. 3) '60-edk2-ovmf-x64.json' (Fedora-33) - secure boot feature disabled, no keys enrolled - With this configuration it will boot all loaders because there is no secure boot feature available in the firmware. - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.fd' and NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.fd'. Currently with libvirt the <os firmware='efi'> will automatically select only option 1) as it is the first available JSON description. There is no other easy way in libvirt to configure options 2) and 3) except for providing all the paths to firmware in <loader> element and NVRAM template in <nvram> element. Now the 'secure' attribute has a bit misleading documentations as it doesn't control whether the feature is enabled/disabled in the firmware but it is used to tell to QEMU if the provided firmware is with secure boot feature enabled/disabled so QEMU knows how to handle the firmware and access to it. We definitely need to improve the documentation. There is another BZ 1906500 that hits the same limitation in libvirt without providing all the paths manually in the XML, you can check the comments for additional details. We need to probably add new attributes/elements to libvirt VM XML to have simple way how to configure options 2) and 3).
(In reply to Pavel Hrdina from comment #5) > Hi, thanks for the report. > > The situation with secure boot and firmwares is a bit complicated. > > One thing to note is that there is no '/usr/share/edk2/ovmf/OVMF_CODE.fd' > in RHEL-8, my guess is that you tried it on Fedora. Correct. I had a long comment written out last week explaining this but BZ was returning HTTP 5xx errors and took my comment with it :) > There are several JSON descriptions of firmware configurations: > > 1) '40-edk2-ovmf-sb.json' (RHEL-8), '40-edk2-ovmf-x64-sb-enrolled.json' (Fedora-33) > > - secure boot feature enabled, keys enrolled > > - With this configuration it will boot only signed loaders, others are rejected > with 'Access denied' or 'permission denied' so similar. > > - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd' and > NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd'. > > > 2) '50-edk2-ovmf.json' (RHEL-8), '50-edk2-ovmf-x64-sb.json' (Fedora-33) > > - secure boot feature enabled, no keys enrolled > > - With this configuration it will boot all loaders because there are no keys > to verify any signature. > > - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd' and > NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.fd'. > > > 3) '60-edk2-ovmf-x64.json' (Fedora-33) > > - secure boot feature disabled, no keys enrolled > > - With this configuration it will boot all loaders because there is no secure > boot feature available in the firmware. > > - This refers to firmware '/usr/share/edk2/ovmf/OVMF_CODE.fd' and > NVRAM template '/usr/share/edk2/ovmf/OVMF_VARS.fd'. > > > Currently with libvirt the <os firmware='efi'> will automatically select only > option 1) as it is the first available JSON description. > > There is no other easy way in libvirt to configure options 2) and 3) except for > providing all the paths to firmware in <loader> element and NVRAM template > in <nvram> element. > > Now the 'secure' attribute has a bit misleading documentations as it doesn't control > whether the feature is enabled/disabled in the firmware but it is used to tell to > QEMU if the provided firmware is with secure boot feature enabled/disabled so QEMU > knows how to handle the firmware and access to it. We definitely need to improve > the documentation. > > There is another BZ 1906500 that hits the same limitation in libvirt without > providing all the paths manually in the XML, you can check the comments for > additional details. > > We need to probably add new attributes/elements to libvirt VM XML to have simple > way how to configure options 2) and 3). Thank you for all the context. I'll feed this into back into the OpenStack Nova RFE. It sounds like we can use libvirt's discovery functionality but not the auto-configuration feature (at least not yet). For what it's worth, something akin to what I was trying to do (enable or disable secure boot via '<loader secure="yes|no"/>') would be fantastic and probably what we'll need to be able to consume this feature.