From 20547e43468d0a2614a448f44013fe2dc88e4c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20L=C3=B6ser?= Date: Fri, 14 Jun 2024 08:59:38 +0200 Subject: [PATCH] Fixes #37562 - Fix local disk boot over network The assumption was that `exit 1` in GRUB2 triggers a boot from the next bootdevice by the firmware and that the `chainloader` command is not working at all when SecureBoot is enabled (`lockdown=y`). These assumptions seems to be wrong. It looks like that distribution vendors patch GRUB2 differently which results in different behavior affecting these assumptions. Some support `chainloader` command, some do simply end up in the BIOS menu when using `exit 1`. As an alternative we can do a "chainload light" and only load the GRUB2 configuration file from local disk. This means that the PXE booted GRUB2 boots the actual kernel from local disk. For successful SecureBoot verification, the following changes are required: https://github.com/theforeman/foreman/pull/9864 The proposed solution would also work when SecureBoot is disabled, however to avoid side effects I propose to only boot next device if SecureBoot is enabled (GRUB2 variable `lockdown=y` [2]). (cherry picked from commit aca4023ee60d2ab70f486829805bacefa271aa7d) --- .../snippet/pxegrub2_chainload.erb | 31 ++++++-- ...rub2_default_local_boot.host4dhcp.snap.txt | 70 +++++++++++++++++-- ...PXEGrub2_global_default.host4dhcp.snap.txt | 70 +++++++++++++++++-- .../pxegrub2_chainload.host4dhcp.snap.txt | 70 +++++++++++++++++-- 4 files changed, 221 insertions(+), 20 deletions(-) diff --git a/app/views/unattended/provisioning_templates/snippet/pxegrub2_chainload.erb b/app/views/unattended/provisioning_templates/snippet/pxegrub2_chainload.erb index e0f29b76f93..314de20f526 100644 --- a/app/views/unattended/provisioning_templates/snippet/pxegrub2_chainload.erb +++ b/app/views/unattended/provisioning_templates/snippet/pxegrub2_chainload.erb @@ -26,6 +26,17 @@ description: | '/EFI/opensuse/grubx64.efi', '/EFI/Microsoft/boot/bootmgfw.efi' ] + config_paths = [ + '/EFI/fedora/grub.cfg', + '/EFI/redhat/grub.cfg', + '/EFI/centos/grub.cfg', + '/EFI/rocky/grub.cfg', + '/EFI/almalinux/grub.cfg', + '/EFI/debian/grub.cfg', + '/EFI/ubuntu/grub.cfg', + '/EFI/sles/grub.cfg', + '/EFI/opensuse/grub.cfg', + ] -%> insmod part_gpt insmod fat @@ -58,13 +69,23 @@ echo if [ "${lockdown}" == "y" ]; then if [ "${default}" == "local" ]; then - set default="next_bootdevice" + set default="grub_config" fi - menuentry 'Booting from next boot device' --id next_bootdevice { - echo "SecureBoot is enabled, attempting next boot device..." - sleep 2 - exit 1 + menuentry 'Loading GRUB2 config from ESP' --id grub_config { +<% + config_paths.each do |config_path| +-%> + echo "Trying <%= config_path %>" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot <%= config_path %> + if [ -f ($chroot)<%= config_path %> ]; then + configfile ($chroot)<%= config_path %> + fi +<% + end +-%> } fi diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_default_local_boot.host4dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_default_local_boot.host4dhcp.snap.txt index 83fae144770..979173f0ab0 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_default_local_boot.host4dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_default_local_boot.host4dhcp.snap.txt @@ -28,13 +28,73 @@ connectefi scsi if [ "${lockdown}" == "y" ]; then if [ "${default}" == "local" ]; then - set default="next_bootdevice" + set default="grub_config" fi - menuentry 'Booting from next boot device' --id next_bootdevice { - echo "SecureBoot is enabled, attempting next boot device..." - sleep 2 - exit 1 + menuentry 'Loading GRUB2 config from ESP' --id grub_config { + echo "Trying /EFI/fedora/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/fedora/grub.cfg + if [ -f ($chroot)/EFI/fedora/grub.cfg ]; then + configfile ($chroot)/EFI/fedora/grub.cfg + fi + echo "Trying /EFI/redhat/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/redhat/grub.cfg + if [ -f ($chroot)/EFI/redhat/grub.cfg ]; then + configfile ($chroot)/EFI/redhat/grub.cfg + fi + echo "Trying /EFI/centos/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/centos/grub.cfg + if [ -f ($chroot)/EFI/centos/grub.cfg ]; then + configfile ($chroot)/EFI/centos/grub.cfg + fi + echo "Trying /EFI/rocky/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/rocky/grub.cfg + if [ -f ($chroot)/EFI/rocky/grub.cfg ]; then + configfile ($chroot)/EFI/rocky/grub.cfg + fi + echo "Trying /EFI/almalinux/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/almalinux/grub.cfg + if [ -f ($chroot)/EFI/almalinux/grub.cfg ]; then + configfile ($chroot)/EFI/almalinux/grub.cfg + fi + echo "Trying /EFI/debian/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/debian/grub.cfg + if [ -f ($chroot)/EFI/debian/grub.cfg ]; then + configfile ($chroot)/EFI/debian/grub.cfg + fi + echo "Trying /EFI/ubuntu/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/ubuntu/grub.cfg + if [ -f ($chroot)/EFI/ubuntu/grub.cfg ]; then + configfile ($chroot)/EFI/ubuntu/grub.cfg + fi + echo "Trying /EFI/sles/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/sles/grub.cfg + if [ -f ($chroot)/EFI/sles/grub.cfg ]; then + configfile ($chroot)/EFI/sles/grub.cfg + fi + echo "Trying /EFI/opensuse/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/opensuse/grub.cfg + if [ -f ($chroot)/EFI/opensuse/grub.cfg ]; then + configfile ($chroot)/EFI/opensuse/grub.cfg + fi } fi diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_global_default.host4dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_global_default.host4dhcp.snap.txt index 76caf487e47..dd4ce7b6f06 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_global_default.host4dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/PXEGrub2/PXEGrub2_global_default.host4dhcp.snap.txt @@ -44,13 +44,73 @@ connectefi scsi if [ "${lockdown}" == "y" ]; then if [ "${default}" == "local" ]; then - set default="next_bootdevice" + set default="grub_config" fi - menuentry 'Booting from next boot device' --id next_bootdevice { - echo "SecureBoot is enabled, attempting next boot device..." - sleep 2 - exit 1 + menuentry 'Loading GRUB2 config from ESP' --id grub_config { + echo "Trying /EFI/fedora/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/fedora/grub.cfg + if [ -f ($chroot)/EFI/fedora/grub.cfg ]; then + configfile ($chroot)/EFI/fedora/grub.cfg + fi + echo "Trying /EFI/redhat/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/redhat/grub.cfg + if [ -f ($chroot)/EFI/redhat/grub.cfg ]; then + configfile ($chroot)/EFI/redhat/grub.cfg + fi + echo "Trying /EFI/centos/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/centos/grub.cfg + if [ -f ($chroot)/EFI/centos/grub.cfg ]; then + configfile ($chroot)/EFI/centos/grub.cfg + fi + echo "Trying /EFI/rocky/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/rocky/grub.cfg + if [ -f ($chroot)/EFI/rocky/grub.cfg ]; then + configfile ($chroot)/EFI/rocky/grub.cfg + fi + echo "Trying /EFI/almalinux/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/almalinux/grub.cfg + if [ -f ($chroot)/EFI/almalinux/grub.cfg ]; then + configfile ($chroot)/EFI/almalinux/grub.cfg + fi + echo "Trying /EFI/debian/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/debian/grub.cfg + if [ -f ($chroot)/EFI/debian/grub.cfg ]; then + configfile ($chroot)/EFI/debian/grub.cfg + fi + echo "Trying /EFI/ubuntu/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/ubuntu/grub.cfg + if [ -f ($chroot)/EFI/ubuntu/grub.cfg ]; then + configfile ($chroot)/EFI/ubuntu/grub.cfg + fi + echo "Trying /EFI/sles/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/sles/grub.cfg + if [ -f ($chroot)/EFI/sles/grub.cfg ]; then + configfile ($chroot)/EFI/sles/grub.cfg + fi + echo "Trying /EFI/opensuse/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/opensuse/grub.cfg + if [ -f ($chroot)/EFI/opensuse/grub.cfg ]; then + configfile ($chroot)/EFI/opensuse/grub.cfg + fi } fi diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/snippet/pxegrub2_chainload.host4dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/snippet/pxegrub2_chainload.host4dhcp.snap.txt index 40d7ff6d62c..bfb76f8a94f 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/snippet/pxegrub2_chainload.host4dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/snippet/pxegrub2_chainload.host4dhcp.snap.txt @@ -24,13 +24,73 @@ connectefi scsi if [ "${lockdown}" == "y" ]; then if [ "${default}" == "local" ]; then - set default="next_bootdevice" + set default="grub_config" fi - menuentry 'Booting from next boot device' --id next_bootdevice { - echo "SecureBoot is enabled, attempting next boot device..." - sleep 2 - exit 1 + menuentry 'Loading GRUB2 config from ESP' --id grub_config { + echo "Trying /EFI/fedora/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/fedora/grub.cfg + if [ -f ($chroot)/EFI/fedora/grub.cfg ]; then + configfile ($chroot)/EFI/fedora/grub.cfg + fi + echo "Trying /EFI/redhat/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/redhat/grub.cfg + if [ -f ($chroot)/EFI/redhat/grub.cfg ]; then + configfile ($chroot)/EFI/redhat/grub.cfg + fi + echo "Trying /EFI/centos/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/centos/grub.cfg + if [ -f ($chroot)/EFI/centos/grub.cfg ]; then + configfile ($chroot)/EFI/centos/grub.cfg + fi + echo "Trying /EFI/rocky/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/rocky/grub.cfg + if [ -f ($chroot)/EFI/rocky/grub.cfg ]; then + configfile ($chroot)/EFI/rocky/grub.cfg + fi + echo "Trying /EFI/almalinux/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/almalinux/grub.cfg + if [ -f ($chroot)/EFI/almalinux/grub.cfg ]; then + configfile ($chroot)/EFI/almalinux/grub.cfg + fi + echo "Trying /EFI/debian/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/debian/grub.cfg + if [ -f ($chroot)/EFI/debian/grub.cfg ]; then + configfile ($chroot)/EFI/debian/grub.cfg + fi + echo "Trying /EFI/ubuntu/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/ubuntu/grub.cfg + if [ -f ($chroot)/EFI/ubuntu/grub.cfg ]; then + configfile ($chroot)/EFI/ubuntu/grub.cfg + fi + echo "Trying /EFI/sles/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/sles/grub.cfg + if [ -f ($chroot)/EFI/sles/grub.cfg ]; then + configfile ($chroot)/EFI/sles/grub.cfg + fi + echo "Trying /EFI/opensuse/grub.cfg" + unset chroot + # add --efidisk-only when using Software RAID + search --file --no-floppy --set=chroot /EFI/opensuse/grub.cfg + if [ -f ($chroot)/EFI/opensuse/grub.cfg ]; then + configfile ($chroot)/EFI/opensuse/grub.cfg + fi } fi