diff --git a/0001-Streamline-BLS-and-improve-PCR-stability.patch b/0001-Streamline-BLS-and-improve-PCR-stability.patch new file mode 100644 index 0000000..8a60e01 --- /dev/null +++ b/0001-Streamline-BLS-and-improve-PCR-stability.patch @@ -0,0 +1,188 @@ +From 8201e8e6fbb7ee992c430679705852ede91efcd6 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 20 Aug 2024 12:14:35 +0800 +Subject: [PATCH] Streamline BLS and improve PCR stability + +Introduce an environment variable enable_blscfg to allow looking for and +reading BLS (Boot Loader Specification) configurations right at startup, +rather than relying on the traditional grub.cfg. The benefit of this +approach is that it eliminates the layer of using an external grub.cfg +to piggyback the blscfg command. This change reduces the complexity of +managing command sequences, which would otherwise complicate the PCR +(Platform Configuration Register) policy. Managing a sequence of +commands can be difficult to maintain and ensure they remain in order +indefinitely. + +Along the way, we can remove the external grub.cfg and have everything +embedded in memdisk and early embedded configurations. This approach +significantly improves the overall stability and makes it easier to +maintain a consistent and predictable PCR outcome. + +The grubenv in the EFI boot directory can be used to override default +settings in the grubbls image, allowing for continued customization. + +By introducing grubbls.efi for managing BLS configuration integration, +all necessary modules are built-in, and sensible default settings are +applied. This allows us to remove the following hardcoded command +sequences in blscfg: + + load_video + set gfxpalyload=keep + insmod gzio + +Since these are now part of the EFI image, this change effectively +simplifies the TPM event log, making it easier to handle with tools like +pcr-oracle or systemd-pcrlock. + +Signed-Off-by: Michael Chang +--- + grub-core/commands/blscfg.c | 4 ++ + grub-core/normal/main.c | 82 +++++++++++++++++++++++++++++++++++++ + include/grub/parser.h | 4 ++ + 3 files changed, 90 insertions(+) + +diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c +index cbe2a289e..e08f35817 100644 +--- a/grub-core/commands/blscfg.c ++++ b/grub-core/commands/blscfg.c +@@ -953,10 +953,14 @@ static void create_entry (struct bls_entry *entry) + + const char *sdval = grub_env_get("save_default"); + bool savedefault = ((NULL != sdval) && (grub_strcmp(sdval, "true") == 0)); ++#ifdef GRUB_MACHINE_EFI ++ src = grub_xasprintf ("%slinux %s%s%s%s\n" ++#else + src = grub_xasprintf ("%sload_video\n" + "set gfxpayload=keep\n" + "insmod gzio\n" + "linux %s%s%s%s\n" ++#endif + "%s%s", + savedefault ? "savedefault\n" : "", + #ifdef GRUB_MACHINE_EMU +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index 03631f07a..8e58ced67 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -113,6 +113,65 @@ read_config_file_getline (char **line, int cont __attribute__ ((unused)), + return GRUB_ERR_NONE; + } + ++#ifdef GRUB_MACHINE_EFI ++ ++static void ++read_envblk_from_cmdpath (void) ++{ ++ const char *cmdpath; ++ char *envfile = NULL; ++ int found = 0; ++ ++ cmdpath = grub_env_get ("cmdpath"); ++ ++ if (cmdpath) ++ envfile = grub_xasprintf ("%s/grubenv", cmdpath); ++ ++ if (envfile) ++ { ++ grub_file_t file; ++ ++ file = grub_file_open (envfile, GRUB_FILE_TYPE_FS_SEARCH ++ | GRUB_FILE_TYPE_NO_DECOMPRESS | GRUB_FILE_TYPE_SKIP_SIGNATURE); ++ if (file) ++ { ++ found = 1; ++ grub_file_close (file); ++ } ++ } ++ ++ if (found) ++ { ++ char *cfg; ++ ++ cfg = grub_xasprintf ("load_env -f %s\n", envfile); ++ grub_parser_execute ((char *)cfg); ++ grub_free (cfg); ++ } ++ ++ grub_free (envfile); ++} ++ ++static grub_menu_t ++read_blscfg (void) ++{ ++ grub_menu_t newmenu; ++ newmenu = grub_env_get_menu (); ++ if (! newmenu) ++ { ++ newmenu = grub_zalloc (sizeof (*newmenu)); ++ if (! newmenu) ++ return 0; ++ ++ grub_env_set_menu (newmenu); ++ } ++ ++ grub_parser_execute ((char *)"blscfg\n"); ++ return newmenu; ++} ++ ++#endif ++ + static grub_menu_t + read_config_file (const char *config) + { +@@ -282,6 +341,26 @@ grub_normal_execute (const char *config, int nested, int batch) + + grub_boot_time ("Executing config file"); + ++#ifdef GRUB_MACHINE_EFI ++ const char *val; ++ ++ val = grub_env_get ("enable_blscfg"); ++ if (val && (val[0] == '1' || val[0] == 'y')) ++ read_envblk_from_cmdpath (); ++ ++ /* Above would be used to override enable_blscfg, so verify again */ ++ val = grub_env_get ("enable_blscfg"); ++ if (val && (val[0] == '1' || val[0] == 'y')) ++ { ++ menu = read_blscfg (); ++ /* Ignore any error. */ ++ grub_errno = GRUB_ERR_NONE; ++ /* unset to let configfile and source commands continue to work */ ++ grub_env_unset ("enable_blscfg"); ++ goto check_batch; ++ } ++#endif ++ + if (config) + { + menu = read_config_file (config); +@@ -307,6 +386,9 @@ grub_normal_execute (const char *config, int nested, int batch) + + grub_boot_time ("Executed config file"); + ++#ifdef GRUB_MACHINE_EFI ++ check_batch: ++#endif + if (! batch) + { + if (menu && menu->size) +diff --git a/include/grub/parser.h b/include/grub/parser.h +index 64f9f5cc2..9d702571a 100644 +--- a/include/grub/parser.h ++++ b/include/grub/parser.h +@@ -86,7 +86,11 @@ struct grub_parser + }; + typedef struct grub_parser *grub_parser_t; + ++#ifdef GRUB_MACHINE_EFI ++grub_err_t EXPORT_FUNC (grub_parser_execute) (char *source); ++#else + grub_err_t grub_parser_execute (char *source); ++#endif + + grub_err_t + grub_rescue_parse_line (char *line, +-- +2.46.0 + diff --git a/0001-bli-Fix-crash-in-get_part_uuid.patch b/0001-bli-Fix-crash-in-get_part_uuid.patch new file mode 100644 index 0000000..5b8ec19 --- /dev/null +++ b/0001-bli-Fix-crash-in-get_part_uuid.patch @@ -0,0 +1,82 @@ +From 552a2de0642bb95dd38fcdb7894ea7e07171975e Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 15 Jul 2024 11:43:07 +0800 +Subject: [PATCH] bli: Fix crash in get_part_uuid + +The get_part_uuid() function made an assumption that the target grub +device is a partition device and accessed device->disk->partition +without checking for NULL. There are four situations where this +assumption is problematic: + +1. The device is a net device instead of a disk. +2. The device is an abstraction device, like LVM, RAID, or CRYPTO, which + is mostly logical "disk" ((lvmid/) and so on). +3. Firmware RAID may present the ESP to grub as an EFI disk (hd0) device + if it is contained within a Linux software RAID. +4. When booting from a cdrom, the ESP is a vfat image indexed by the El + Torito boot catalog. The boot device is set to (cd0), corresponding + to the cdrom image mounted as an iso9660 filesystem. + +As a result, get_part_uuid() could lead to a NULL pointer dereference +and trigger a synchronous exception during boot if the ESP falls into +one of these categories. This patch fixes the problem by adding the +necessary checks to handle cases where the ESP is not a partition +device. + +Additionally, to avoid disrupting the boot process, this patch relaxes +the severity of the errors in this context to non-critical. Errors will +be logged, but they will not prevent the boot process from continuing. + +Fixes: e0fa7dc84 (bli: Add a module for the Boot Loader Interface) +Signed-off-by: Michael Chang +Reviewed-By: Oliver Steffen +--- + grub-core/commands/bli.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/grub-core/commands/bli.c b/grub-core/commands/bli.c +index e0d8a54f7..298c5f70a 100644 +--- a/grub-core/commands/bli.c ++++ b/grub-core/commands/bli.c +@@ -48,6 +48,22 @@ get_part_uuid (const char *device_name, char **part_uuid) + if (device == NULL) + return grub_error (grub_errno, N_("cannot open device: %s"), device_name); + ++ if (device->disk == NULL) ++ { ++ grub_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name); ++ *part_uuid = NULL; ++ grub_device_close (device); ++ return GRUB_ERR_NONE; ++ } ++ ++ if (device->disk->partition == NULL) ++ { ++ grub_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name); ++ *part_uuid = NULL; ++ grub_device_close (device); ++ return GRUB_ERR_NONE; ++ } ++ + disk = grub_disk_open (device->disk->name); + if (disk == NULL) + { +@@ -99,7 +115,7 @@ set_loader_device_part_uuid (void) + + status = get_part_uuid (device_name, &part_uuid); + +- if (status == GRUB_ERR_NONE) ++ if (status == GRUB_ERR_NONE && part_uuid) + status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid, + GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | + GRUB_EFI_VARIABLE_RUNTIME_ACCESS); +@@ -117,4 +133,6 @@ GRUB_MOD_INIT (bli) + GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | + GRUB_EFI_VARIABLE_RUNTIME_ACCESS); + set_loader_device_part_uuid (); ++ /* No error here is critical, other than being logged */ ++ grub_print_error (); + } +-- +2.46.0 + diff --git a/grub2.changes b/grub2.changes index 97361ea..3cd15cd 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Tue Aug 13 07:12:58 UTC 2024 - Michael Chang + +- Introduces a new package, grub2-x86_64-efi-bls, which includes a + straightforward grubbls.efi file. This file can be copied to the EFI System + Partition (ESP) along with boot fragments in the Boot Loader Specification + (BLS) format + * 0001-Streamline-BLS-and-improve-PCR-stability.patch +- Fix crash in bli module (bsc#1226497) + * 0001-bli-Fix-crash-in-get_part_uuid.patch + +------------------------------------------------------------------- +Tue Aug 13 02:42:42 UTC 2024 - Michael Chang + +- Rework package dependencies: grub2-common now includes common userland + utilities and is required by grub2 platform packages. grub2 is now a meta + package that pulls in the default platform package. + ------------------------------------------------------------------- Fri Aug 2 08:44:40 UTC 2024 - Michael Chang diff --git a/grub2.spec b/grub2.spec index 2ca9eaf..b4fbd6c 100644 --- a/grub2.spec +++ b/grub2.spec @@ -406,7 +406,27 @@ Patch215: 0008-blscfg-reading-bls-fragments-if-boot-present.patch Patch216: 0009-10_linux-Some-refinement-for-BLS.patch Patch217: 0001-net-drivers-ieee1275-ofnet-Remove-200-ms-timeout-in-.patch Patch218: grub2-s390x-set-hostonly.patch +Patch219: 0001-bli-Fix-crash-in-get_part_uuid.patch +Patch220: 0001-Streamline-BLS-and-improve-PCR-stability.patch +# Always requires a default cpu-platform package +Requires: grub2-%{grubarch} = %{version}-%{release} + +%if 0%{?only_x86_64:1} +ExclusiveArch: x86_64 +%else +ExclusiveArch: %{ix86} x86_64 ppc ppc64 ppc64le s390x aarch64 %{arm} riscv64 +%endif + +%description +This is the second version of the GRUB (Grand Unified Bootloader), a +highly configurable and customizable bootloader with modular +architecture. It support rich scale of kernel formats, file systems, +computer architectures and hardware devices. + +%package common +Summary: Utilies to manage grub +Group: System/Boot Requires: gettext-runtime %if 0%{?suse_version} >= 1140 %ifnarch s390x @@ -417,9 +437,6 @@ Recommends: os-prober Suggests: libburnia-tools Suggests: mtools %endif -%if ! 0%{?only_efi:1} -Requires: grub2-%{grubarch} = %{version}-%{release} -%endif %ifarch s390x # required utilities by grub2-s390x-04-grub2-install.patch # use 'showconsole' to determine console device. (bnc#876743) @@ -436,25 +453,15 @@ Requires: powerpc-utils Recommends: memtest86+ %endif -%if 0%{?only_x86_64:1} -ExclusiveArch: x86_64 -%else -ExclusiveArch: %{ix86} x86_64 ppc ppc64 ppc64le s390x aarch64 %{arm} riscv64 -%endif - -%description -This is the second version of the GRUB (Grand Unified Bootloader), a -highly configurable and customizable bootloader with modular -architecture. It support rich scale of kernel formats, file systems, -computer architectures and hardware devices. - +%description common This package includes user space utlities to manage GRUB on your system. %package branding-upstream Summary: Upstream branding for GRUB2's graphical console Group: System/Fhs -Requires: %{name} = %{version} +BuildArch: noarch +Requires: %{name}-common = %{version} %description branding-upstream Upstream branding for GRUB2's graphical console @@ -467,8 +474,8 @@ Group: System/Boot %if "%{platform}" != "emu" BuildArch: noarch %endif -Requires: %{name} = %{version} -Requires(post): %{name} = %{version} +Requires: %{name}-common = %{version} +Requires(post): %{name}-common = %{version} %{?update_bootloader_requires} %description %{grubarch} @@ -516,8 +523,8 @@ BuildArch: noarch # Without it grub-install is broken so break the package as well if unavailable Requires: efibootmgr Requires(post): efibootmgr -Requires: %{name} = %{version} -Requires(post): %{name} = %{version} +Requires: %{name}-common = %{version} +Requires(post): %{name}-common = %{version} %{?update_bootloader_requires} %{?fde_tpm_update_requires} Provides: %{name}-efi = %{version}-%{release} @@ -529,6 +536,14 @@ bootloader with modular architecture. It supports rich variety of kernel format file systems, computer architectures and hardware devices. This subpackage provides support for EFI systems. +%package %{grubefiarch}-bls +Summary: Image for Boot Loader Specification (BLS) support on %{grubefiarch} +Group: System/Boot +BuildArch: noarch + +%description %{grubefiarch}-bls +Custom EFI build tailored for Boot Loader Specification (BLS) support. + %package %{grubefiarch}-extras Summary: Unsupported modules for %{grubefiarch} @@ -592,7 +607,7 @@ Unsupported modules for %{name}-%{grubxenarch} Summary: Grub2's snapper plugin Group: System/Fhs -Requires: %{name} = %{version} +Requires: %{name}-common = %{version} Requires: libxml2-tools Supplements: packageand(snapper:grub2) BuildArch: noarch @@ -756,6 +771,57 @@ mksquashfs ./fonts memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress ./grub-mkimage -O %{grubefiarch} -o grub.efi --memdisk=./memdisk.sqsh --prefix= %{?sbat_generation:--sbat sbat.csv} \ -d grub-core ${GRUB_MODULES} +rm memdisk.sqsh + +# Building grubbls.efi +# FIXME: error out if theme_vendor missing +theme_vendor=$(find %{_datadir}/%{name}/themes -type f -name activate-theme -exec dirname {} \; -quit) +theme_vendor=${theme_vendor##*/} + +# [ -n "$theme_vendor" ] || { echo "ERROR: no grub2 theme vendor found, missing branding package ??"; exit 1 } + +mkdir -p ./boot/grub +cp -rf "%{_datadir}/%{name}/themes/$theme_vendor" ./boot/grub/themes +rm -f "./boot/grub/themes/activate-theme" + +cat > ./grubbls.cfg <<'EOF' + +regexp --set 1:root '\((.*)\)' "$cmdpath" + +set timeout=8 +set gfxmode=auto +set gfxpayload=keep +set enable_blscfg=1 + +terminal_input console +terminal_output console +terminal_output --append gfxterm + +loadfont (memdisk)/boot/grub/themes/DejaVuSans-Bold14.pf2 +loadfont (memdisk)/boot/grub/themes/DejaVuSans10.pf2 +loadfont (memdisk)/boot/grub/themes/DejaVuSans12.pf2 +loadfont (memdisk)/boot/grub/themes/ascii.pf2 + +set theme=(memdisk)/boot/grub/themes/theme.txt +export theme + +EOF + +%if 0%{?suse_version} > 1500 +tar --sort=name -cf - ./boot | mksquashfs - memdisk.sqsh -tar -comp xz -quiet -no-progress +%else +mksquashfs ./boot memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress +%endif + +./grub-mkimage -O %{grubefiarch} \ + -o grubbls.efi \ + --memdisk=./memdisk.sqsh \ + -c ./grubbls.cfg \ + %{?sbat_generation:--sbat sbat.csv} \ + -d grub-core \ + all_video boot font gfxmenu gfxterm gzio halt jpeg minicmd normal part_gpt png reboot video \ + fat tpm tpm2 memdisk tar squash4 xzio blscfg linux bli regexp loadenv test echo true sleep + %ifarch x86_64 aarch64 if test -e %{_sourcedir}/_projectcert.crt ; then prjsubject=$(openssl x509 -in %{_sourcedir}/_projectcert.crt -noout -subject_hash) @@ -947,6 +1013,7 @@ install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/. %ifarch x86_64 ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi %endif +install -m 644 grubbls.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/. # Create grub.efi link to system efi directory # This is for tools like kiwi not fiddling with the path @@ -968,7 +1035,7 @@ EoM %endif %ifarch x86_64 aarch64 -export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi" +export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi" install -m 444 grub.der %{buildroot}/%{sysefidir}/ %endif @@ -1101,10 +1168,10 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %fdupes %buildroot%{_libdir} %fdupes %buildroot%{_datadir} -%pre +%pre common %service_add_pre grub2-once.service -%post +%post common %service_add_post grub2-once.service %if ! 0%{?only_efi:1} @@ -1132,19 +1199,14 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %endif -%preun +%preun common %service_del_preun grub2-once.service -%postun +%postun common %service_del_postun grub2-once.service -%files -f %{name}.lang +%files %defattr(-,root,root,-) -%if 0%{?suse_version} < 1500 -%doc COPYING -%else -%license COPYING -%endif %doc AUTHORS %doc NEWS README %doc THANKS TODO ChangeLog @@ -1152,6 +1214,14 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %ifarch s390x %doc README.ibm3215 %endif + +%files common -f %{name}.lang +%if 0%{?suse_version} < 1500 +%doc COPYING +%else +%license COPYING +%endif +%defattr(-,root,root,-) %dir /boot/%{name} %ghost %attr(600, root, root) /boot/%{name}/grub.cfg %{_datadir}/bash-completion/completions/grub* @@ -1333,6 +1403,10 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %{sysefidir}/grub.der %endif +%files %{grubefiarch}-bls +%defattr(-,root,root,-) +%{_datadir}/%{name}/%{grubefiarch}/grubbls.efi + %files %{grubefiarch}-extras -f %{grubefiarch}-mod-extras.lst %defattr(-,root,root,-) %dir %{_datadir}/%{name}/%{grubefiarch}