From dc857889be1c788397c49cfd3d5a3ab13e736338 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Thu, 31 Aug 2023 15:05:19 +0200 Subject: [PATCH 01/27] spec: Modified posttrans to harden grub config detection Resolves: #2235692 Signed-off-by: Nicolas Frayer --- grub2.spec | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/grub2.spec b/grub2.spec index 3d205816..162769e5 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 97%{?dist} +Release: 98%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -348,8 +348,8 @@ if test ! -f ${EFI_HOME}/grub.cfg; then grub2-mkconfig -o ${EFI_HOME}/grub.cfg fi -if grep -q "configfile" ${EFI_HOME}/grub.cfg; then - exit 0 # already unified, nothing to do +if ((grep -q "configfile" ${EFI_HOME}/grub.cfg || grep -q "source" ${EFI_HOME}/grub.cfg) && ! grep -q "# It is automatically generated by grub2-mkconfig using templates" ${EFI_HOME}/grub.cfg); then + exit 0 #Already unified fi # create a stub grub2 config in EFI @@ -544,6 +544,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Thu Aug 31 2023 Nicolas Frayer - 2.06-98 +- spec: Modified posttrans to harden grub config detection +- Resolves: #2235692 + * Tue Aug 22 2023 Nicolas Frayer - 2.06-97 - efi/http: change uint32_t to uintn_t From 84d684cdeb51d899a2d13a933d829d4a1e1d9b36 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Tue, 12 Sep 2023 22:24:05 +0200 Subject: [PATCH 02/27] spec: Use systemd presets and macros for units in tools package Resolves: #2230575 Signed-off-by: Christian Glombek --- ...Install-section-to-aux-systemd-units.patch | 52 +++++++++++++++++++ grub.patches | 1 + grub2.spec | 38 ++++++++------ 3 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 0335-Add-Install-section-to-aux-systemd-units.patch diff --git a/0335-Add-Install-section-to-aux-systemd-units.patch b/0335-Add-Install-section-to-aux-systemd-units.patch new file mode 100644 index 00000000..c7268501 --- /dev/null +++ b/0335-Add-Install-section-to-aux-systemd-units.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christian Glombek +Date: Wed, 9 Aug 2023 18:11:25 +0200 +Subject: [PATCH] Add [Install] section to aux systemd units + +Currently in Fedora, these services are statically enabled by symlinks, +with no other way to disable them than to manually delete those symlinks. +This is problematic in Fedora IoT, where grub-boot-success.timer is +not supposed to be enabled. + +This change adds `[Install]` sections to all systemd units that are +currently enabled statically, so that they can be enabled dynamically +via presets or manually instead. +--- + docs/grub-boot-indeterminate.service | 3 +++ + docs/grub-boot-success.timer | 3 +++ + util/systemd/grub-systemd-integration.service.in | 3 +++ + 3 files changed, 9 insertions(+) + +diff --git a/docs/grub-boot-indeterminate.service b/docs/grub-boot-indeterminate.service +index 6c8dcb186b63..5bcb474a3d31 100644 +--- a/docs/grub-boot-indeterminate.service ++++ b/docs/grub-boot-indeterminate.service +@@ -9,3 +9,6 @@ Before=system-update-pre.target + [Service] + Type=oneshot + ExecStart=/usr/bin/grub2-editenv - incr boot_indeterminate ++ ++[Install] ++WantedBy=system-update.target +diff --git a/docs/grub-boot-success.timer b/docs/grub-boot-success.timer +index 406f17200560..1d124cccc146 100644 +--- a/docs/grub-boot-success.timer ++++ b/docs/grub-boot-success.timer +@@ -5,3 +5,6 @@ ConditionVirtualization=!container + + [Timer] + OnActiveSec=2min ++ ++[Install] ++WantedBy=timers.target +diff --git a/util/systemd/grub-systemd-integration.service.in b/util/systemd/grub-systemd-integration.service.in +index c81fb594ce17..22ca1ca4885e 100644 +--- a/util/systemd/grub-systemd-integration.service.in ++++ b/util/systemd/grub-systemd-integration.service.in +@@ -6,3 +6,6 @@ ConditionPathExists=/run/systemd/reboot-to-boot-loader-menu + + [Service] + ExecStart=@libexecdir@/@grubdirname@/systemd-integration.sh ++ ++[Install] ++WantedBy=reboot.target diff --git a/grub.patches b/grub.patches index 7e0f096c..47616374 100644 --- a/grub.patches +++ b/grub.patches @@ -332,3 +332,4 @@ Patch0331: 0331-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch Patch0332: 0332-emu-Add-switch-root-to-grub-emu.patch Patch0333: 0333-util-Enable-default-kernel-for-updates.patch Patch0334: 0334-efi-http-change-uint32_t-to-uintn_t.patch +Patch0335: 0335-Add-Install-section-to-aux-systemd-units.patch diff --git a/grub2.spec b/grub2.spec index 162769e5..8fd1e448 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 98%{?dist} +Release: 99%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -62,8 +62,8 @@ BuildRequires: squashfs-tools BuildRequires: texinfo BuildRequires: xz-devel -# For %%_userunitdir macro -BuildRequires: systemd +# For %%_userunitdir and %%systemd_* macros +BuildRequires: systemd-rpm-macros %ifarch %{efi_arch} BuildRequires: pesign >= 0.99-8 @@ -114,6 +114,7 @@ Requires: gettext-runtime os-prober file Requires(pre): dracut Requires(pre): grep Requires(pre): sed +%{?systemd_requires} %description tools %{desc} @@ -271,17 +272,8 @@ install -d -m 0755 %{buildroot}%{_sysconfdir}/kernel/install.d/ # Install systemd user service to set the boot_success flag install -D -m 0755 -t %{buildroot}%{_userunitdir} \ docs/grub-boot-success.{timer,service} -install -d -m 0755 %{buildroot}%{_userunitdir}/timers.target.wants -ln -s ../grub-boot-success.timer \ - %{buildroot}%{_userunitdir}/timers.target.wants # Install systemd system-update unit to set boot_indeterminate for offline-upd install -D -m 0755 -t %{buildroot}%{_unitdir} docs/grub-boot-indeterminate.service -install -d -m 0755 %{buildroot}%{_unitdir}/system-update.target.wants -install -d -m 0755 %{buildroot}%{_unitdir}/reboot.target.wants -ln -s ../grub-boot-indeterminate.service \ - %{buildroot}%{_unitdir}/system-update.target.wants -ln -s ../grub2-systemd-integration.service \ - %{buildroot}%{_unitdir}/reboot.target.wants # Don't run debuginfo on all the grub modules and whatnot; it just # rejects them, complains, and slows down extraction. @@ -332,6 +324,21 @@ elif [ -f /etc/grub.d/01_users ] && \ fi fi +%post tools +%systemd_post grub-boot-indeterminate.service +%systemd_post grub-systemd-integration.service +%systemd_user_post grub-boot-success.timer + +%preun tools +%systemd_preun grub-boot-indeterminate.service +%systemd_preun grub-systemd-integration.service +%systemd_user_preun grub-boot-success.timer + +%postun tools +%systemd_postun_with_restart grub-boot-indeterminate.service +%systemd_postun_with_restart grub-systemd-integration.service +%systemd_user_postun_with_restart grub-boot-success.timer + %posttrans common set -eu @@ -427,11 +434,8 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %{_sysconfdir}/grub.d/README %{_userunitdir}/grub-boot-success.timer %{_userunitdir}/grub-boot-success.service -%{_userunitdir}/timers.target.wants %{_unitdir}/grub-boot-indeterminate.service -%{_unitdir}/system-update.target.wants %{_unitdir}/grub2-systemd-integration.service -%{_unitdir}/reboot.target.wants %{_unitdir}/systemd-logind.service.d %{_infodir}/grub2* %{_datarootdir}/grub/* @@ -544,6 +548,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Sep 01 2023 Christian Glombek - 2.06-99 +- spec: Use systemd presets and macros for units in tools package +- Resolves: #2230575 + * Thu Aug 31 2023 Nicolas Frayer - 2.06-98 - spec: Modified posttrans to harden grub config detection - Resolves: #2235692 From c4218f0de98c4a5c84e830424b5582b1a4747a7b Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Wed, 13 Sep 2023 00:10:53 +0200 Subject: [PATCH 03/27] arm64: Use proper memory type for kernel allocation Resolves: #2149020 Signed-off-by: Nicolas Frayer --- ...er-memory-type-for-kernel-allocation.patch | 44 +++++++++++++++++++ grub.patches | 1 + grub2.spec | 6 ++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch diff --git a/0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch b/0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch new file mode 100644 index 00000000..e77fcbf6 --- /dev/null +++ b/0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Tue, 28 Jun 2022 23:06:46 +0200 +Subject: [PATCH] arm64: Use proper memory type for kernel allocation + +Currently, the kernel pages are allocated with type EFI_LOADER_DATA. +While the vast majority of systems will happily execute code from those +pages (i.e. don't care about memory protection), the Microsoft Surface +Pro X stalls, as this memory is not designated as "executable". + +Therefore, allocate the kernel pages as EFI_LOADER_CODE to request +memory that is actually executable. + +Signed-off-by: Maximilian Luz +--- + grub-core/loader/arm64/linux.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 419f2201df8b..a3a193c255e9 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -26,7 +26,9 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include + #include +@@ -403,7 +405,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_loader_unset(); + + kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); +- kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); ++ kernel_alloc_addr = grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, ++ kernel_alloc_pages, ++ GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_CODE); + grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); + if (!kernel_alloc_addr) + { diff --git a/grub.patches b/grub.patches index 47616374..b870cefe 100644 --- a/grub.patches +++ b/grub.patches @@ -333,3 +333,4 @@ Patch0332: 0332-emu-Add-switch-root-to-grub-emu.patch Patch0333: 0333-util-Enable-default-kernel-for-updates.patch Patch0334: 0334-efi-http-change-uint32_t-to-uintn_t.patch Patch0335: 0335-Add-Install-section-to-aux-systemd-units.patch +Patch0336: 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch diff --git a/grub2.spec b/grub2.spec index 8fd1e448..65f59156 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 99%{?dist} +Release: 100%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Sep 13 2023 Nicolas Frayer - 2.06-100 +- arm64: Use proper memory type for kernel allocation +- Resolves: #2149020 + * Fri Sep 01 2023 Christian Glombek - 2.06-99 - spec: Use systemd presets and macros for units in tools package - Resolves: #2230575 From 851dea6ca0b25be7489566d1efc0bae05c8650e2 Mon Sep 17 00:00:00 2001 From: Christian Glombek Date: Thu, 28 Sep 2023 19:05:51 +0200 Subject: [PATCH 04/27] spec: Fix grub2-systemd-integration.service name Signed-off-by: Christian Glombek --- grub2.spec | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/grub2.spec b/grub2.spec index 65f59156..6a8ad61e 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 100%{?dist} +Release: 101%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -326,17 +326,17 @@ fi %post tools %systemd_post grub-boot-indeterminate.service -%systemd_post grub-systemd-integration.service +%systemd_post grub2-systemd-integration.service %systemd_user_post grub-boot-success.timer %preun tools %systemd_preun grub-boot-indeterminate.service -%systemd_preun grub-systemd-integration.service +%systemd_preun grub2-systemd-integration.service %systemd_user_preun grub-boot-success.timer %postun tools %systemd_postun_with_restart grub-boot-indeterminate.service -%systemd_postun_with_restart grub-systemd-integration.service +%systemd_postun_with_restart grub2-systemd-integration.service %systemd_user_postun_with_restart grub-boot-success.timer %posttrans common @@ -548,6 +548,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Thu Sep 28 2023 Christian Glombek - 2.06-101 +- spec: Fix grub2-systemd-integration.service name + * Wed Sep 13 2023 Nicolas Frayer - 2.06-100 - arm64: Use proper memory type for kernel allocation - Resolves: #2149020 From fa21cb15244b59258b92651b373734a0fd83fd17 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Fri, 29 Sep 2023 18:06:49 +0200 Subject: [PATCH 05/27] ofdisk: Fix missing #include in ofdisk.c Signed-off-by: Nicolas Frayer --- 0337-Fix-missing-include-in-ofdisk.c.patch | 28 ++++++++++++++++++++++ grub.patches | 1 + grub2.spec | 5 +++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 0337-Fix-missing-include-in-ofdisk.c.patch diff --git a/0337-Fix-missing-include-in-ofdisk.c.patch b/0337-Fix-missing-include-in-ofdisk.c.patch new file mode 100644 index 00000000..84a12405 --- /dev/null +++ b/0337-Fix-missing-include-in-ofdisk.c.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 29 Sep 2023 10:56:11 -0400 +Subject: [PATCH] Fix missing #include in ofdisk.c + +Recently we started building with -Werror=implicit-function-declaration, +and discovered that ofdisk.c is missing an include to declare +grub_env_get(). + +This patch adds that #include. + +Signed-off-by: Peter Jones +--- + grub-core/disk/ieee1275/ofdisk.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c +index 5534684..6e33d5d 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + static char *last_devpath; + static grub_ieee1275_ihandle_t last_ihandle; diff --git a/grub.patches b/grub.patches index b870cefe..5ae522f4 100644 --- a/grub.patches +++ b/grub.patches @@ -334,3 +334,4 @@ Patch0333: 0333-util-Enable-default-kernel-for-updates.patch Patch0334: 0334-efi-http-change-uint32_t-to-uintn_t.patch Patch0335: 0335-Add-Install-section-to-aux-systemd-units.patch Patch0336: 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch +Patch0337: 0337-Fix-missing-include-in-ofdisk.c.patch diff --git a/grub2.spec b/grub2.spec index 6a8ad61e..74cf9716 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 101%{?dist} +Release: 102%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Sep 29 2023 Nicolas Frayer - 2.06-102 +- ofdisk: Fix missing #include in ofdisk.c + * Thu Sep 28 2023 Christian Glombek - 2.06-101 - spec: Fix grub2-systemd-integration.service name From 767345ab81b17d4028cdfab37f720ff5c4ce0019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 27 Sep 2023 17:05:21 +0200 Subject: [PATCH 06/27] Rename installed kernel to match name used in boot entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mkbls() function would write 'linux /vmlinuz-${kernelver}' into the boot loader entry. But the code that actually copies the file would use the original file name with a version suffix ('cp -aT "$i" "/boot/${i##*/}-${KERNEL_VERSION}"'). In case of a local kernel build calling /sbin/installkernel this file name was e.g. 'bzImage', so we would end up with '/bzImage-${KERNEL_VERSION}', which of course doesn't match '/vmlinuz-*'. The script would later call 'grub2-mkrel' on the name taken from the boot entry which would fail because the file does not exist. Rename the argument to "vmlinuz", so that both parts match. Tested by doing a local kernel build with 'sudo make install' at the end. Signed-off-by: Zbigniew Jędrzejewski-Szmek --- 20-grub.install | 7 ++++++- grub2.spec | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/20-grub.install b/20-grub.install index 8a86cc07..952322f3 100755 --- a/20-grub.install +++ b/20-grub.install @@ -54,8 +54,13 @@ EOF case "$COMMAND" in add) if [[ "${KERNEL_DIR}" != "/boot" ]]; then + # rename to match the name used in the pseudo-BLS snippet above + rm -f "/boot/vmlinuz-${KERNEL_VERSION}" + cp -aT "${KERNEL_IMAGE}" "/boot/vmlinuz-${KERNEL_VERSION}" + command -v restorecon &>/dev/null && \ + restorecon -R "/boot/vmlinuz-${KERNEL_VERSION}" + for i in \ - "$KERNEL_IMAGE" \ "$KERNEL_DIR"/System.map \ "$KERNEL_DIR"/config \ "$KERNEL_DIR"/zImage.stub \ diff --git a/grub2.spec b/grub2.spec index 74cf9716..a99ce0eb 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 102%{?dist} +Release: 103%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Sep 29 2023 Zbigniew Jedrzejewski-Szmek - 1:2.06-103 +- Rename installed kernel to match name used in boot entry +- Resolves: #2239008 + * Fri Sep 29 2023 Nicolas Frayer - 2.06-102 - ofdisk: Fix missing #include in ofdisk.c From 46c50c4f60c668637ba85eeb55ac32d683bf2911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 28 Sep 2023 12:05:19 +0200 Subject: [PATCH 07/27] Do not preserve ownership or xattrs on copied files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As noticed in https://bugzilla.redhat.com/show_bug.cgi?id=2239008#c16, when compiling a kernel as a user and doing 'sudo make install', and when using a non-vfat fs for the install destination, the file would end up owned by the user. This is not useful at all, so let's only preserve the timestamps on the copied file, no other attributes. Signed-off-by: Zbigniew Jędrzejewski-Szmek --- 20-grub.install | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/20-grub.install b/20-grub.install index 952322f3..58a998ee 100755 --- a/20-grub.install +++ b/20-grub.install @@ -56,7 +56,7 @@ case "$COMMAND" in if [[ "${KERNEL_DIR}" != "/boot" ]]; then # rename to match the name used in the pseudo-BLS snippet above rm -f "/boot/vmlinuz-${KERNEL_VERSION}" - cp -aT "${KERNEL_IMAGE}" "/boot/vmlinuz-${KERNEL_VERSION}" + cp --preserve=timestamps -T "${KERNEL_IMAGE}" "/boot/vmlinuz-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/vmlinuz-${KERNEL_VERSION}" @@ -68,7 +68,7 @@ case "$COMMAND" in do [[ -e "$i" ]] || continue rm -f "/boot/${i##*/}-${KERNEL_VERSION}" - cp -aT "$i" "/boot/${i##*/}-${KERNEL_VERSION}" + cp --preserve=timestamps -T "$i" "/boot/${i##*/}-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/${i##*/}-${KERNEL_VERSION}" done @@ -76,7 +76,7 @@ case "$COMMAND" in i="$KERNEL_DIR/.${KERNEL_IMAGE##*/}.hmac" if [[ -e "$i" ]]; then rm -f "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" - cp -a "$i" "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" + cp --preserve=timestamps "$i" "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" command -v restorecon &>/dev/null && \ restorecon "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" fi @@ -158,7 +158,7 @@ case "$COMMAND" in if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then BLS_DEBUG="$(echo ${BLS_TARGET} | sed -e "s/${KERNEL_VERSION}/${KERNEL_VERSION}~debug/")" - cp -aT "${BLS_TARGET}" "${BLS_DEBUG}" + cp --preserve=timestamps -T "${BLS_TARGET}" "${BLS_DEBUG}" TITLE="$(grep '^title[ \t]' "${BLS_DEBUG}" | sed -e 's/^title[ \t]*//')" OPTIONS="$(echo "${BOOT_OPTIONS[*]} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')" sed -i -e "s/^title.*/title ${TITLE}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${BLS_DEBUG}" From 801601daab4feeeccde7f02873bb1c3a350c4eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 28 Sep 2023 12:09:09 +0200 Subject: [PATCH 08/27] Let ln and cp remove the destination files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional change, but makes the script a bit shorter. Signed-off-by: Zbigniew Jędrzejewski-Szmek --- 20-grub.install | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/20-grub.install b/20-grub.install index 58a998ee..1114cf53 100755 --- a/20-grub.install +++ b/20-grub.install @@ -55,8 +55,7 @@ case "$COMMAND" in add) if [[ "${KERNEL_DIR}" != "/boot" ]]; then # rename to match the name used in the pseudo-BLS snippet above - rm -f "/boot/vmlinuz-${KERNEL_VERSION}" - cp --preserve=timestamps -T "${KERNEL_IMAGE}" "/boot/vmlinuz-${KERNEL_VERSION}" + cp --remove-destination --preserve=timestamps -T "${KERNEL_IMAGE}" "/boot/vmlinuz-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/vmlinuz-${KERNEL_VERSION}" @@ -67,16 +66,14 @@ case "$COMMAND" in "$KERNEL_DIR"/dtb do [[ -e "$i" ]] || continue - rm -f "/boot/${i##*/}-${KERNEL_VERSION}" - cp --preserve=timestamps -T "$i" "/boot/${i##*/}-${KERNEL_VERSION}" + cp --remove-destination --preserve=timestamps -T "$i" "/boot/${i##*/}-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/${i##*/}-${KERNEL_VERSION}" done # hmac is .vmlinuz-.hmac so needs a special treatment i="$KERNEL_DIR/.${KERNEL_IMAGE##*/}.hmac" if [[ -e "$i" ]]; then - rm -f "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" - cp --preserve=timestamps "$i" "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" + cp --remove-destination --preserve=timestamps "$i" "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" command -v restorecon &>/dev/null && \ restorecon "/boot/.${KERNEL_IMAGE##*/}-${KERNEL_VERSION}.hmac" fi @@ -84,16 +81,14 @@ case "$COMMAND" in # symvers is symvers-.gz symlink, needs a special treatment i="$KERNEL_DIR/symvers.gz" if [[ -e "$i" ]]; then - rm -f "/boot/symvers-${KERNEL_VERSION}.gz" - ln -s "$i" "/boot/symvers-${KERNEL_VERSION}.gz" + ln -fs "$i" "/boot/symvers-${KERNEL_VERSION}.gz" command -v restorecon &>/dev/null && \ restorecon "/boot/symvers-${KERNEL_VERSION}.gz" fi # symvers is symvers-.bz symlink, needs a special treatment i="$KERNEL_DIR/symvers.bz" if [[ -e "$i" ]]; then - rm -f "/boot/symvers-${KERNEL_VERSION}.bz" - ln -s "$i" "/boot/symvers-${KERNEL_VERSION}.bz" + ln -fs "$i" "/boot/symvers-${KERNEL_VERSION}.bz" command -v restorecon &>/dev/null && \ restorecon "/boot/symvers-${KERNEL_VERSION}.bz" fi From eb2de6793d9c2849918b040f5dfaa5d56f60581a Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Fri, 25 Aug 2023 13:31:05 +0200 Subject: [PATCH 09/27] Don't run 20-grub.install for UKIs When kernel-install is called for a UKI, 20-grub.install copies it to /boot which is totally unneeded, UKIs are now handled by the standard systemd's 90-uki-copy.install (systemd-253+) correctly which places them to the ESP. Signed-off-by: Vitaly Kuznetsov --- 20-grub.install | 3 +++ 1 file changed, 3 insertions(+) diff --git a/20-grub.install b/20-grub.install index 1114cf53..5ef21321 100755 --- a/20-grub.install +++ b/20-grub.install @@ -19,6 +19,9 @@ MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID # If ${BOOT_DIR_ABS} exists, some other boot loader is active. [[ -d "${BOOT_DIR_ABS}" ]] && exit 0 +# UKIs are BLS type 2 entries, 90-uki-copy.install takes care of them +[ "x$KERNEL_INSTALL_LAYOUT" != "xuki" ] || exit 0 + BLS_DIR="/boot/loader/entries" mkbls() { From 43a488b92036b2e3a0e7e1664845ba73ee1ef9a3 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 10 Oct 2023 18:43:25 +0000 Subject: [PATCH 10/27] 20-grub.install: Copy device-tree directory recursively 8800efcb0bea replaced '-a' with '--preserve=timestamps' to avoid preserving ownership information on non vfat file systems. This breaks copying of the 'dtb' directory on aarch64 systems since '-a' implies '-r'. Add '-r' to the single place where 'dtb/' is copied to /boot. Resolves: #2243060 Fixes: 8800efcb0bea ("Do not preserve ownership or xattrs on copied files") Signed-off-by: Janne Grunau Signed-off-by: Nicolas Frayer --- 20-grub.install | 2 +- grub2.spec | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/20-grub.install b/20-grub.install index 5ef21321..afc706dd 100755 --- a/20-grub.install +++ b/20-grub.install @@ -69,7 +69,7 @@ case "$COMMAND" in "$KERNEL_DIR"/dtb do [[ -e "$i" ]] || continue - cp --remove-destination --preserve=timestamps -T "$i" "/boot/${i##*/}-${KERNEL_VERSION}" + cp --remove-destination --preserve=timestamps -rT "$i" "/boot/${i##*/}-${KERNEL_VERSION}" command -v restorecon &>/dev/null && \ restorecon -R "/boot/${i##*/}-${KERNEL_VERSION}" done diff --git a/grub2.spec b/grub2.spec index a99ce0eb..f744a47d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 103%{?dist} +Release: 104%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Oct 11 2023 Janne Grunau - 2.06-104 +- 20-grub.install: Copy device-tree directory recursively +- Resolves: #2243060 + * Fri Sep 29 2023 Zbigniew Jedrzejewski-Szmek - 1:2.06-103 - Rename installed kernel to match name used in boot entry - Resolves: #2239008 From 64d211d94f33185b8cde7db4fbb5bb132b3c60f7 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Fri, 20 Oct 2023 18:40:02 +0200 Subject: [PATCH 11/27] kern/ieee1275/init: ppc64: Restrict high memory in presence of fadump Signed-off-by: Nicolas Frayer --- ...it-ppc64-Restrict-high-memory-in-pre.patch | 226 ++++++++++++++++++ grub.patches | 1 + grub2.spec | 6 +- 3 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch diff --git a/0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch b/0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch new file mode 100644 index 00000000..5c7e1a38 --- /dev/null +++ b/0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch @@ -0,0 +1,226 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Tue, 25 Jul 2023 13:23:10 -0400 +Subject: [PATCH] kern/ieee1275/init: ppc64: Restrict high memory in presence + of fadump + +When a kernel dump is present then restrict the high memory regions to +avoid allocating memory where the kernel dump resides. Use the +ibm,kernel-dump node under /rtas to determine whether a kernel dump exists +and up to which limit grub can use available memory. Set the +upper_mem_limit to the size of the kernel dump section of type +'REAL_MODE_REGION' and therefore only allow grub's memory usage for high +addresses from RMO_ADDR_MAX to 'upper_mem_limit'. This means that grub can +use high memory in the range of RMO_ADDR_MAX (768MB) to upper_mem_limit and +the kernel-dump memory regions above 'upper_mem_limit' remain untouched. +This change has no effect on memory allocations below 'linux_rmo_save' +(typically at 640MB). + +Also, fall back to allocating below rmo_linux_save in case the chunk of +memory there would be larger than the chunk of memory above RMO_ADDR_MAX. +This can for example occur if a free memory area is found starting at 300MB +extending up to 1GB but a kernel dump is located at 768MB and therefore +does not allow the allocation of the high memory area but requiring to use +the chunk starting at 300MB to avoid an unnecessary out-of-memory +condition. + +Signed-off-by: Stefan Berger +Reviewed-by: Hari Bathini +Cc: Pavithra Prakash +Cc: Michael Ellerman +Cc: Carolyn Scherrer +Cc: Mahesh Salgaonkar +Cc: Sourabh Jain +--- + grub-core/kern/ieee1275/init.c | 144 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 142 insertions(+), 2 deletions(-) + +diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c +index 3d4ad9d1f162..8e7f742fad46 100644 +--- a/grub-core/kern/ieee1275/init.c ++++ b/grub-core/kern/ieee1275/init.c +@@ -17,6 +17,8 @@ + * along with GRUB. If not, see . + */ + ++#include /* offsetof() */ ++ + #include + #include + #include +@@ -198,6 +200,96 @@ grub_claim_heap (void) + #else + /* Helpers for mm on powerpc. */ + ++/* ibm,kernel-dump data structures */ ++struct kd_section ++{ ++ grub_uint32_t flags; ++ grub_uint16_t src_datatype; ++#define KD_SRC_DATATYPE_REAL_MODE_REGION 0x0011 ++ grub_uint16_t error_flags; ++ grub_uint64_t src_address; ++ grub_uint64_t num_bytes; ++ grub_uint64_t act_bytes; ++ grub_uint64_t dst_address; ++} GRUB_PACKED; ++ ++#define MAX_KD_SECTIONS 10 ++ ++struct kernel_dump ++{ ++ grub_uint32_t format; ++ grub_uint16_t num_sections; ++ grub_uint16_t status_flags; ++ grub_uint32_t offset_1st_section; ++ grub_uint32_t num_blocks; ++ grub_uint64_t start_block; ++ grub_uint64_t num_blocks_avail; ++ grub_uint32_t offet_path_string; ++ grub_uint32_t max_time_allowed; ++ struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */ ++} GRUB_PACKED; ++ ++/* ++ * Determine if a kernel dump exists and if it does, then determine the highest ++ * address that grub can use for memory allocations. ++ * The caller must have initialized *highest to rmo_top. *highest will not ++ * be modified if no kernel dump is found. ++ */ ++static void ++check_kernel_dump (grub_uint64_t *highest) ++{ ++ struct kernel_dump kernel_dump; ++ grub_ssize_t kernel_dump_size; ++ grub_ieee1275_phandle_t rtas; ++ struct kd_section *kds; ++ grub_size_t i; ++ ++ /* If there's a kernel-dump it must have at least one section */ ++ if (grub_ieee1275_finddevice ("/rtas", &rtas) || ++ grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump, ++ sizeof (kernel_dump), &kernel_dump_size) || ++ kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1])) ++ return; ++ ++ kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump)); ++ ++ if (grub_be_to_cpu32 (kernel_dump.format) != 1) ++ { ++ grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"), ++ grub_be_to_cpu32 (kernel_dump.format)); ++ return; ++ } ++ ++ if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS) ++ { ++ grub_printf (_("Error: Too many kernel dump sections: %d\n"), ++ grub_be_to_cpu32 (kernel_dump.num_sections)); ++ return; ++ } ++ ++ for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++) ++ { ++ kds = (struct kd_section *) ((grub_addr_t) &kernel_dump + ++ grub_be_to_cpu32 (kernel_dump.offset_1st_section) + ++ i * sizeof (struct kd_section)); ++ /* sanity check the address is within the 'kernel_dump' struct */ ++ if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds)) ++ { ++ grub_printf (_("Error: 'kds' address beyond last available section\n")); ++ return; ++ } ++ ++ if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) && ++ (grub_be_to_cpu64 (kds->src_address) == 0)) ++ { ++ *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes)); ++ break; ++ } ++ } ++ ++ return; ++} ++ + /* + * How much memory does OF believe exists in total? + * +@@ -277,10 +369,31 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + * + * Finally, we also want to make sure that when grub loads the kernel, + * it isn't going to use up all the memory we're trying to reserve! So +- * enforce our entire RUNTIME_MIN_SPACE here: ++ * enforce our entire RUNTIME_MIN_SPACE here (no fadump): ++ * ++ * | Top of memory == upper_mem_limit -| ++ * | | ++ * | available | ++ * | | ++ * |---------- 768 MB ----------| ++ * | | ++ * | reserved | ++ * | | ++ * |--- 768 MB - runtime min space ---| ++ * | | ++ * | available | ++ * | | ++ * |---------- 0 MB ----------| ++ * ++ * In case fadump is used, we allow the following: + * + * |---------- Top of memory ----------| + * | | ++ * | unavailable | ++ * | (kernel dump area) | ++ * | | ++ * |--------- upper_mem_limit ---------| ++ * | | + * | available | + * | | + * |---------- 768 MB ----------| +@@ -335,17 +448,44 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + } + else + { ++ grub_uint64_t upper_mem_limit = rmo_top; ++ grub_uint64_t orig_addr = addr; ++ ++ check_kernel_dump (&upper_mem_limit); ++ + /* + * we order these cases to prefer higher addresses and avoid some + * splitting issues ++ * The following shows the order of variables: ++ * no kernel dump: linux_rmo_save < RMO_ADDR_MAX <= upper_mem_limit == rmo_top ++ * with kernel dump: liuxx_rmo_save < RMO_ADDR_MAX <= upper_mem_limit <= rmo_top + */ +- if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX) ++ if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX && upper_mem_limit >= RMO_ADDR_MAX) + { + grub_dprintf ("ieee1275", + "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n", + addr, addr + len, RMO_ADDR_MAX, addr + len); + len = (addr + len) - RMO_ADDR_MAX; + addr = RMO_ADDR_MAX; ++ ++ /* We must not exceed the upper_mem_limit (assuming it's >= RMO_ADDR_MAX) */ ++ if (addr + len > upper_mem_limit) ++ { ++ /* take the bigger chunk from either below linux_rmo_save or above upper_mem_limit */ ++ len = upper_mem_limit - addr; ++ if (orig_addr < linux_rmo_save && linux_rmo_save - orig_addr > len) ++ { ++ /* lower part is bigger */ ++ addr = orig_addr; ++ len = linux_rmo_save - addr; ++ } ++ ++ grub_dprintf ("ieee1275", "re-adjusted region to: (%llx -> %llx)\n", ++ addr, addr + len); ++ ++ if (len == 0) ++ return 0; ++ } + } + else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save)) + { diff --git a/grub.patches b/grub.patches index 5ae522f4..28241dad 100644 --- a/grub.patches +++ b/grub.patches @@ -335,3 +335,4 @@ Patch0334: 0334-efi-http-change-uint32_t-to-uintn_t.patch Patch0335: 0335-Add-Install-section-to-aux-systemd-units.patch Patch0336: 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch Patch0337: 0337-Fix-missing-include-in-ofdisk.c.patch +Patch0338: 0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch diff --git a/grub2.spec b/grub2.spec index f744a47d..1cf935a5 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 104%{?dist} +Release: 105%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Oct 20 2023 Nicolas Frayer - 2.06-105 +- kern/ieee1275/init: ppc64: Restrict high memory in presence +of fadump + * Wed Oct 11 2023 Janne Grunau - 2.06-104 - 20-grub.install: Copy device-tree directory recursively - Resolves: #2243060 From 1ea248daea184ecb166300d1e3de0064fbf5fab0 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Mon, 13 Nov 2023 16:05:48 +0100 Subject: [PATCH 12/27] util: grub-install on EFI if forced Resolves: #1917213 Resolves: #2240994 Signed-off-by: Nicolas Frayer --- 0339-grub-install-on-EFI-if-forced.patch | 77 ++++++++++++++++++++++++ grub.patches | 1 + grub2.spec | 7 ++- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 0339-grub-install-on-EFI-if-forced.patch diff --git a/0339-grub-install-on-EFI-if-forced.patch b/0339-grub-install-on-EFI-if-forced.patch new file mode 100644 index 00000000..ad231ac5 --- /dev/null +++ b/0339-grub-install-on-EFI-if-forced.patch @@ -0,0 +1,77 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Marta Lewandowska +Date: Fri, 13 Oct 2023 09:13:41 +0200 +Subject: [PATCH] grub-install on EFI if forced + +UEFI Secure Boot requires signed grub binaries to work, so grub- +install should not be used. However, users who have Secure Boot +disabled and wish to use the command should not be prevented from +doing so if they invoke --force. + +fixes bz#1917213 / bz#2240994 + +Signed-off-by: Marta Lewandowska +--- + util/grub-install.c | 42 ++++++++++++++++++++++++++---------------- + 1 file changed, 26 insertions(+), 16 deletions(-) + +diff --git a/util/grub-install.c b/util/grub-install.c +index 5babc7af5518..162162bec6e2 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -899,22 +899,6 @@ main (int argc, char *argv[]) + + platform = grub_install_get_target (grub_install_source_directory); + +- switch (platform) +- { +- case GRUB_INSTALL_PLATFORM_ARM_EFI: +- case GRUB_INSTALL_PLATFORM_ARM64_EFI: +- case GRUB_INSTALL_PLATFORM_I386_EFI: +- case GRUB_INSTALL_PLATFORM_IA64_EFI: +- case GRUB_INSTALL_PLATFORM_X86_64_EFI: +- is_efi = 1; +- grub_util_error (_("this utility cannot be used for EFI platforms" +- " because it does not support UEFI Secure Boot")); +- break; +- default: +- is_efi = 0; +- break; +- } +- + { + char *platname = grub_install_get_platform_name (platform); + fprintf (stderr, _("Installing for %s platform.\n"), platname); +@@ -1027,6 +1011,32 @@ main (int argc, char *argv[]) + grub_hostfs_init (); + grub_host_init (); + ++ switch (platform) ++ { ++ case GRUB_INSTALL_PLATFORM_I386_EFI: ++ case GRUB_INSTALL_PLATFORM_X86_64_EFI: ++ case GRUB_INSTALL_PLATFORM_ARM_EFI: ++ case GRUB_INSTALL_PLATFORM_ARM64_EFI: ++ case GRUB_INSTALL_PLATFORM_RISCV32_EFI: ++ case GRUB_INSTALL_PLATFORM_RISCV64_EFI: ++ case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ is_efi = 1; ++ if (!force) ++ grub_util_error (_("This utility should not be used for EFI platforms" ++ " because it does not support UEFI Secure Boot." ++ " If you really wish to proceed, invoke the --force" ++ " option.\nMake sure Secure Boot is disabled before" ++ " proceeding")); ++ break; ++ default: ++ is_efi = 0; ++ break; ++ ++ /* pacify warning. */ ++ case GRUB_INSTALL_PLATFORM_MAX: ++ break; ++ } ++ + /* Find the EFI System Partition. */ + if (is_efi) + { diff --git a/grub.patches b/grub.patches index 28241dad..90e54622 100644 --- a/grub.patches +++ b/grub.patches @@ -336,3 +336,4 @@ Patch0335: 0335-Add-Install-section-to-aux-systemd-units.patch Patch0336: 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch Patch0337: 0337-Fix-missing-include-in-ofdisk.c.patch Patch0338: 0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch +Patch0339: 0339-grub-install-on-EFI-if-forced.patch diff --git a/grub2.spec b/grub2.spec index 1cf935a5..070233bf 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 105%{?dist} +Release: 106%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -548,6 +548,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Mon Nov 13 2023 Nicolas Frayer - 2.06-106 +- util: grub-install on EFI if forced +- Resolves: #1917213 +- Resolves: #2240994 + * Fri Oct 20 2023 Nicolas Frayer - 2.06-105 - kern/ieee1275/init: ppc64: Restrict high memory in presence of fadump From c88723f778673c3341d577219dcf884a142a8f67 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 14 Nov 2023 12:15:47 +0100 Subject: [PATCH 13/27] spec: Fix enablement of grub services and timer Fix enablement of grub services and timer: - Switch back to static enablement for grub services in tools package - Add %%triggerpostun to apply grub-boot-success.timer preset when upgrading from older versions where this was not a preset Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2247635 Signed-off-by: Christian Glombek Signed-off-by: Hans de Goede --- grub2.spec | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/grub2.spec b/grub2.spec index 070233bf..027ee653 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 106%{?dist} +Release: 107%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -274,6 +274,12 @@ install -D -m 0755 -t %{buildroot}%{_userunitdir} \ docs/grub-boot-success.{timer,service} # Install systemd system-update unit to set boot_indeterminate for offline-upd install -D -m 0755 -t %{buildroot}%{_unitdir} docs/grub-boot-indeterminate.service +install -d -m 0755 %{buildroot}%{_unitdir}/system-update.target.wants +install -d -m 0755 %{buildroot}%{_unitdir}/reboot.target.wants +ln -s ../grub-boot-indeterminate.service \ + %{buildroot}%{_unitdir}/system-update.target.wants +ln -s ../grub2-systemd-integration.service \ + %{buildroot}%{_unitdir}/reboot.target.wants # Don't run debuginfo on all the grub modules and whatnot; it just # rejects them, complains, and slows down extraction. @@ -325,20 +331,19 @@ elif [ -f /etc/grub.d/01_users ] && \ fi %post tools -%systemd_post grub-boot-indeterminate.service -%systemd_post grub2-systemd-integration.service %systemd_user_post grub-boot-success.timer %preun tools -%systemd_preun grub-boot-indeterminate.service -%systemd_preun grub2-systemd-integration.service %systemd_user_preun grub-boot-success.timer %postun tools -%systemd_postun_with_restart grub-boot-indeterminate.service -%systemd_postun_with_restart grub2-systemd-integration.service %systemd_user_postun_with_restart grub-boot-success.timer +%triggerpostun tools -- grub2-tools < 1:2.06-107 +# grub-boot-success.timer was moved from a hard symlink under /lib/systemd +# to a preset, apply the preset when upgrading from pre-preset versions +/usr/lib/systemd/systemd-update-helper install-user-units grub-boot-success.timer + %posttrans common set -eu @@ -435,7 +440,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %{_userunitdir}/grub-boot-success.timer %{_userunitdir}/grub-boot-success.service %{_unitdir}/grub-boot-indeterminate.service +%{_unitdir}/system-update.target.wants %{_unitdir}/grub2-systemd-integration.service +%{_unitdir}/reboot.target.wants %{_unitdir}/systemd-logind.service.d %{_infodir}/grub2* %{_datarootdir}/grub/* @@ -548,7 +555,13 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog -* Mon Nov 13 2023 Nicolas Frayer - 2.06-106 +* Tue Nov 14 2023 Hans de Goede - 2.06-107 +- spec: Switch back to static enablement for grub services in tools package +- spec: Add %%triggerpostun to apply grub-boot-success.timer preset + when upgrading from older versions where this was not a preset +- Resolves: #2247635 + +* Mon Nov 6 2023 Nicolas Frayer - 2.06-106 - util: grub-install on EFI if forced - Resolves: #1917213 - Resolves: #2240994 From b02f48fd74a331fb2f8e9f855f936700ed870ddc Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Wed, 15 Nov 2023 12:20:21 +0100 Subject: [PATCH 14/27] Remove [Install] section from aux systemd units Related: #2247635 Signed-off-by: Nicolas Frayer --- ...stall-section-from-aux-systemd-units.patch | 33 +++++++++++++++++++ grub.patches | 1 + grub2.spec | 6 +++- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 0340-Remove-Install-section-from-aux-systemd-units.patch diff --git a/0340-Remove-Install-section-from-aux-systemd-units.patch b/0340-Remove-Install-section-from-aux-systemd-units.patch new file mode 100644 index 00000000..1a62cddb --- /dev/null +++ b/0340-Remove-Install-section-from-aux-systemd-units.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christian Glombek +Date: Tue, 14 Nov 2023 07:54:59 +0100 +Subject: [PATCH] Remove [Install] section from aux systemd units + +See https://bugzilla.redhat.com/show_bug.cgi?id=2247635#c7 +--- + docs/grub-boot-indeterminate.service | 3 --- + util/systemd/grub-systemd-integration.service.in | 3 --- + 2 files changed, 6 deletions(-) + +diff --git a/docs/grub-boot-indeterminate.service b/docs/grub-boot-indeterminate.service +index 5bcb474a3d31..6c8dcb186b63 100644 +--- a/docs/grub-boot-indeterminate.service ++++ b/docs/grub-boot-indeterminate.service +@@ -9,6 +9,3 @@ Before=system-update-pre.target + [Service] + Type=oneshot + ExecStart=/usr/bin/grub2-editenv - incr boot_indeterminate +- +-[Install] +-WantedBy=system-update.target +diff --git a/util/systemd/grub-systemd-integration.service.in b/util/systemd/grub-systemd-integration.service.in +index 22ca1ca4885e..c81fb594ce17 100644 +--- a/util/systemd/grub-systemd-integration.service.in ++++ b/util/systemd/grub-systemd-integration.service.in +@@ -6,6 +6,3 @@ ConditionPathExists=/run/systemd/reboot-to-boot-loader-menu + + [Service] + ExecStart=@libexecdir@/@grubdirname@/systemd-integration.sh +- +-[Install] +-WantedBy=reboot.target diff --git a/grub.patches b/grub.patches index 90e54622..7228ddef 100644 --- a/grub.patches +++ b/grub.patches @@ -337,3 +337,4 @@ Patch0336: 0336-arm64-Use-proper-memory-type-for-kernel-allocation.patch Patch0337: 0337-Fix-missing-include-in-ofdisk.c.patch Patch0338: 0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch Patch0339: 0339-grub-install-on-EFI-if-forced.patch +Patch0340: 0340-Remove-Install-section-from-aux-systemd-units.patch diff --git a/grub2.spec b/grub2.spec index 027ee653..fb66f171 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 107%{?dist} +Release: 108%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Tue Nov 14 2023 Nicolas Frayer - 2.06-108 +- Remove [Install] section from aux systemd units +- Related: #2247635 + * Tue Nov 14 2023 Hans de Goede - 2.06-107 - spec: Switch back to static enablement for grub services in tools package - spec: Add %%triggerpostun to apply grub-boot-success.timer preset From c27e33d7575835cbc96c26588cddcf917a18c694 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Thu, 9 Nov 2023 18:05:37 +0100 Subject: [PATCH 15/27] Linker: added --no-warn-rwx-segments linker option added --no-warn-rwx-segments as build will fail after ld.bfd default options have been changed. Please refer: https://fedoraproject.org/wiki/Changes/Linker_Error_On_Security_Issues Signed-off-by: Nicolas Frayer --- grub.macros | 4 ++-- grub2.spec | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/grub.macros b/grub.macros index 959b9729..0198ffc3 100644 --- a/grub.macros +++ b/grub.macros @@ -15,7 +15,7 @@ %endif # gnulib actively ignores CFLAGS because it's terrible -%global cc_equals "CC=%{ccpath} -fPIE -Wl,-z,noexecstack" +%global cc_equals "CC=%{ccpath} -fPIE -Wl,-z,noexecstack -Wl,--no-warn-rwx-segments" %global cflags_sed \\\ sed \\\ @@ -68,7 +68,7 @@ )} %global efi_host_ldflags %{expand:%%(echo %{host_ldflags})} -%global target_ldflags %{expand:%%(echo %{build_ldflags} -static | %{ldflags_sed})} +%global target_ldflags %{expand:%%(echo %{build_ldflags} -Wl,--no-warn-rwx-segments -static | %{ldflags_sed})} %global legacy_target_ldflags \\\ %{expand:%%(echo %{target_ldflags} | \\\ %{ldflags_sed} \\\ diff --git a/grub2.spec b/grub2.spec index fb66f171..4fba8400 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 108%{?dist} +Release: 109%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Nov 15 2023 Nicolas Frayer - 2.06-109 +- Linker: added --no-warn-rwx-segments as build will fail after +ld.bfd default options have been changed. +https://fedoraproject.org/wiki/Changes/Linker_Error_On_Security_Issues + * Tue Nov 14 2023 Nicolas Frayer - 2.06-108 - Remove [Install] section from aux systemd units - Related: #2247635 From 6b9f32bc1ec0b23430f30c2f8dacaf863f574a4f Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Fri, 1 Dec 2023 11:22:36 +0100 Subject: [PATCH 16/27] fs/xfs: Add several fixes/improvements to xfs fs from upstream Resolves: #2247926 Signed-off-by: Nicolas Frayer --- 0341-fs-Remove-trailing-whitespaces.patch | 1681 +++++++++++++++++ ...s-xfs-Fix-memory-leaks-in-XFS-module.patch | 47 + ...s-found-while-fuzzing-the-XFS-filesy.patch | 106 ++ ...-short-form-directory-data-boundary-.patch | 47 + ...xfs-Fix-XFS-directory-extent-parsing.patch | 168 ++ ...-extent-counters-incompat-feature-su.patch | 115 ++ grub.patches | 6 + grub2.spec | 6 +- 8 files changed, 2175 insertions(+), 1 deletion(-) create mode 100644 0341-fs-Remove-trailing-whitespaces.patch create mode 100644 0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch create mode 100644 0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch create mode 100644 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch create mode 100644 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch create mode 100644 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch diff --git a/0341-fs-Remove-trailing-whitespaces.patch b/0341-fs-Remove-trailing-whitespaces.patch new file mode 100644 index 00000000..a876f6b1 --- /dev/null +++ b/0341-fs-Remove-trailing-whitespaces.patch @@ -0,0 +1,1681 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Elyes Haouas +Date: Fri, 4 Mar 2022 07:41:59 +0100 +Subject: [PATCH] fs: Remove trailing whitespaces + +Signed-off-by: Elyes Haouas +Reviewed-by: Daniel Kiper +--- + grub-core/fs/affs.c | 4 +- + grub-core/fs/archelp.c | 4 +- + grub-core/fs/bfs.c | 10 +- + grub-core/fs/cpio_common.c | 2 +- + grub-core/fs/fat.c | 6 +- + grub-core/fs/fshelp.c | 6 +- + grub-core/fs/hfs.c | 14 +-- + grub-core/fs/hfsplus.c | 8 +- + grub-core/fs/hfspluscomp.c | 6 +- + grub-core/fs/iso9660.c | 12 +-- + grub-core/fs/minix.c | 6 +- + grub-core/fs/nilfs2.c | 8 +- + grub-core/fs/ntfs.c | 8 +- + grub-core/fs/reiserfs.c | 2 +- + grub-core/fs/romfs.c | 8 +- + grub-core/fs/squash4.c | 26 ++--- + grub-core/fs/udf.c | 2 +- + grub-core/fs/ufs.c | 4 +- + grub-core/fs/xfs.c | 2 +- + grub-core/fs/zfs/zfs.c | 224 ++++++++++++++++++++-------------------- + grub-core/fs/zfs/zfs_fletcher.c | 12 +-- + grub-core/fs/zfs/zfs_sha256.c | 14 +-- + grub-core/fs/zfs/zfscrypt.c | 14 +-- + 23 files changed, 201 insertions(+), 201 deletions(-) + +diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c +index cafcd0fba916..0d90e9d1a895 100644 +--- a/grub-core/fs/affs.c ++++ b/grub-core/fs/affs.c +@@ -345,7 +345,7 @@ grub_affs_create_node (grub_fshelp_node_t dir, + if (len > sizeof (fil->name)) + len = sizeof (fil->name); + *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; +- ++ + (*node)->di = *fil; + for (nest = 0; nest < 8; nest++) + { +@@ -408,7 +408,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, + node = orig_node = grub_zalloc (sizeof (*node)); + if (!node) + return 1; +- ++ + *node = *dir; + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) + return 1; +diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c +index 0cf544f6fdfe..998de88b865c 100644 +--- a/grub-core/fs/archelp.c ++++ b/grub-core/fs/archelp.c +@@ -75,7 +75,7 @@ handle_symlink (struct grub_archelp_data *data, + || !arcops->get_link_target) + return GRUB_ERR_NONE; + flen = grub_strlen (fn); +- if (grub_memcmp (*name, fn, flen) != 0 ++ if (grub_memcmp (*name, fn, flen) != 0 + || ((*name)[flen] != 0 && (*name)[flen] != '/')) + return GRUB_ERR_NONE; + rest = *name + flen; +@@ -251,7 +251,7 @@ grub_archelp_open (struct grub_archelp_data *data, + grub_uint32_t mode; + grub_int32_t mtime; + int restart; +- ++ + if (arcops->find_file (data, &fn, &mtime, &mode)) + goto fail; + +diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c +index 47dbe2011a14..a75876010d30 100644 +--- a/grub-core/fs/bfs.c ++++ b/grub-core/fs/bfs.c +@@ -530,13 +530,13 @@ iterate_in_b_tree (grub_disk_t disk, + err = read_b_node (disk, sb, ino, + node_off, + &node, +- &key_data, ++ &key_data, + &keylen_idx, + &key_values); + + if (err) + return 0; +- ++ + for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++) + { + char c; +@@ -682,7 +682,7 @@ find_in_b_tree (grub_disk_t disk, + level--; + grub_free (node); + continue; +- } ++ } + } + else if (level != 0 + && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys)) +@@ -827,7 +827,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) + grub_err_t err; + err = grub_disk_read (disk, SUPERBLOCK, 0, sizeof (*sb), sb); + if (err == GRUB_ERR_OUT_OF_RANGE) +- return grub_error (GRUB_ERR_BAD_FS, ++ return grub_error (GRUB_ERR_BAD_FS, + #ifdef MODE_AFS + "not an AFS filesystem" + #else +@@ -843,7 +843,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) + || (grub_bfs_to_cpu32 (sb->bsize) + != (1U << grub_bfs_to_cpu32 (sb->log2_bsize))) + || grub_bfs_to_cpu32 (sb->log2_bsize) < GRUB_DISK_SECTOR_BITS) +- return grub_error (GRUB_ERR_BAD_FS, ++ return grub_error (GRUB_ERR_BAD_FS, + #ifdef MODE_AFS + "not an AFS filesystem" + #else +diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c +index 4e885d62313e..5d41b6fdbe1c 100644 +--- a/grub-core/fs/cpio_common.c ++++ b/grub-core/fs/cpio_common.c +@@ -117,7 +117,7 @@ grub_cpio_get_link_target (struct grub_archelp_data *data) + if (!ret) + return NULL; + +- err = grub_disk_read (data->disk, 0, data->dofs, data->size, ++ err = grub_disk_read (data->disk, 0, data->dofs, data->size, + ret); + if (err) + { +diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c +index ff6200c5be5d..c5efed724124 100644 +--- a/grub-core/fs/fat.c ++++ b/grub-core/fs/fat.c +@@ -246,7 +246,7 @@ grub_fat_mount (grub_disk_t disk) + #ifdef MODE_EXFAT + if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ", + sizeof (bpb.oem_name)) != 0) +- goto fail; ++ goto fail; + #endif + + /* Get the sizes of logical sectors and clusters. */ +@@ -321,7 +321,7 @@ grub_fat_mount (grub_disk_t disk) + #endif + + #ifdef MODE_EXFAT +- data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) ++ data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) + << data->logical_sector_bits); + data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count) + << data->logical_sector_bits); +@@ -694,7 +694,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, + { + int j; + for (j = 0; j < 15; j++) +- ctxt->unibuf[slots * 15 + j] ++ ctxt->unibuf[slots * 15 + j] + = grub_le_to_cpu16 (sec.type_specific.file_name.str[j]); + slots++; + } +diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c +index a2d0d297a520..cb41934b4fec 100644 +--- a/grub-core/fs/fshelp.c ++++ b/grub-core/fs/fshelp.c +@@ -215,7 +215,7 @@ find_file (char *currpath, + break; + + push_node (ctx, foundnode, foundtype); +- ++ + /* Read in the symlink and follow it. */ + if (ctx->currnode->type == GRUB_FSHELP_SYMLINK) + { +@@ -326,7 +326,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, + enum grub_fshelp_filetype expecttype) + { + return grub_fshelp_find_file_real (path, rootnode, foundnode, +- iterate_dir, NULL, ++ iterate_dir, NULL, + read_symlink, expecttype); + + } +@@ -339,7 +339,7 @@ grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode, + enum grub_fshelp_filetype expecttype) + { + return grub_fshelp_find_file_real (path, rootnode, foundnode, +- NULL, lookup_file, ++ NULL, lookup_file, + read_symlink, expecttype); + + } +diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c +index f419965d154f..91dc0e69c3de 100644 +--- a/grub-core/fs/hfs.c ++++ b/grub-core/fs/hfs.c +@@ -883,7 +883,7 @@ grub_hfs_iterate_dir_it_dir (struct grub_hfs_node *hnd __attribute ((unused)), + { + struct grub_hfs_catalog_key *ckey = rec->key; + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; +- ++ + /* Stop when the entries do not match anymore. */ + if (ckey->parent_dir != ctx->dir_be) + return 1; +@@ -1077,7 +1077,7 @@ macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len, + { + *optr++ = ':'; + continue; +- } ++ } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr; +@@ -1094,7 +1094,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) + grub_uint8_t *end = to + 31; + grub_uint8_t *optr = to; + const char *iptr = from; +- ++ + while (*iptr && optr < end) + { + int i, clen; +@@ -1104,7 +1104,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) + *optr++ = '/'; + iptr++; + continue; +- } ++ } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr++; +@@ -1165,7 +1165,7 @@ lookup_file (grub_fshelp_node_t dir, + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; +- ++ + (*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid); + (*foundnode)->fdrec = fdrec; + (*foundnode)->data = dir->data; +@@ -1266,7 +1266,7 @@ grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + .hook_data = hook_data + }; + grub_fshelp_node_t found = NULL; +- ++ + grub_dl_ref (my_mod); + + data = grub_hfs_mount (device->disk); +@@ -1295,7 +1295,7 @@ grub_hfs_open (struct grub_file *file, const char *name) + { + struct grub_hfs_data *data; + grub_fshelp_node_t found = NULL; +- ++ + grub_dl_ref (my_mod); + + data = grub_hfs_mount (file->device->disk); +diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c +index 19c7b3367987..6337cbfcbec6 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -19,7 +19,7 @@ + + /* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ + +-#define grub_fshelp_node grub_hfsplus_file ++#define grub_fshelp_node grub_hfsplus_file + #include + #include + #include +@@ -146,7 +146,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + { + struct grub_hfsplus_btnode *nnode = 0; + grub_disk_addr_t blksleft = fileblock; +- struct grub_hfsplus_extent *extents = node->compressed ++ struct grub_hfsplus_extent *extents = node->compressed + ? &node->resource_extents[0] : &node->extents[0]; + + while (1) +@@ -477,7 +477,7 @@ grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, + + if (extkey_a->type < extkey_b->type) + return -1; +- ++ + akey = grub_be_to_cpu32 (extkey_a->start); + if (akey > extkey_b->start) + return 1; +@@ -568,7 +568,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, + struct grub_hfsplus_key_internal *key, + int (*compare_keys) (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb), +- struct grub_hfsplus_btnode **matchnode, ++ struct grub_hfsplus_btnode **matchnode, + grub_off_t *keyoffset) + { + grub_uint64_t currnode; +diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c +index d76f3f137a92..095ea48c9a62 100644 +--- a/grub-core/fs/hfspluscomp.c ++++ b/grub-core/fs/hfspluscomp.c +@@ -179,7 +179,7 @@ hfsplus_read_compressed_real (struct grub_hfsplus_file *node, + return len0; + } + +-static grub_err_t ++static grub_err_t + hfsplus_open_compressed_real (struct grub_hfsplus_file *node) + { + grub_err_t err; +@@ -306,8 +306,8 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node) + + GRUB_MOD_INIT(hfspluscomp) + { +- grub_hfsplus_open_compressed = hfsplus_open_compressed_real; +- grub_hfsplus_read_compressed = hfsplus_read_compressed_real; ++ grub_hfsplus_open_compressed = hfsplus_open_compressed_real; ++ grub_hfsplus_read_compressed = hfsplus_read_compressed_real; + } + + GRUB_MOD_FINI(hfspluscomp) +diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c +index ac011950a64f..91817ec1f5ad 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -181,7 +181,7 @@ static grub_err_t + iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int64_t *nix) + { + struct grub_datetime datetime; +- ++ + if (! i->year[0] && ! i->year[1] + && ! i->year[2] && ! i->year[3] + && ! i->month[0] && ! i->month[1] +@@ -198,7 +198,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int64_t *nix) + datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0'); + datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); + datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); +- ++ + if (!grub_datetime2unixtime (&datetime, nix)) + return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date"); + *nix -= i->offset * 60 * 15; +@@ -216,7 +216,7 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int64_t *nix) + datetime.hour = i->hour; + datetime.minute = i->minute; + datetime.second = i->second; +- ++ + if (!grub_datetime2unixtime (&datetime, nix)) + return 0; + *nix -= i->offset * 60 * 15; +@@ -499,7 +499,7 @@ grub_iso9660_mount (grub_disk_t disk) + static char * + grub_iso9660_read_symlink (grub_fshelp_node_t node) + { +- return node->have_symlink ++ return node->have_symlink + ? grub_strdup (node->symlink + + (node->have_dirents) * sizeof (node->dirents[0]) + - sizeof (node->dirents)) : grub_strdup (""); +@@ -549,7 +549,7 @@ add_part (struct iterate_dir_ctx *ctx, + ctx->symlink = new; + + grub_memcpy (ctx->symlink + size, part, len2); +- ctx->symlink[size + len2] = 0; ++ ctx->symlink[size + len2] = 0; + } + + static grub_err_t +@@ -1106,7 +1106,7 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) + } + + /* Get writing time of filesystem. */ +-static grub_err_t ++static grub_err_t + grub_iso9660_mtime (grub_device_t device, grub_int64_t *timebuf) + { + struct grub_iso9660_data *data; +diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c +index 3cd18c85b302..953df11916b8 100644 +--- a/grub-core/fs/minix.c ++++ b/grub-core/fs/minix.c +@@ -98,10 +98,10 @@ struct grub_minix_sblock + grub_uint32_t max_file_size; + grub_uint32_t zones; + grub_uint16_t magic; +- ++ + grub_uint16_t pad2; + grub_uint16_t block_size; +- grub_uint8_t disk_version; ++ grub_uint8_t disk_version; + }; + #else + struct grub_minix_sblock +@@ -351,7 +351,7 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino) + int offs = (ino % (GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_minix_inode)) + * sizeof (struct grub_minix_inode)); +- ++ + grub_disk_read (data->disk, block, offs, + sizeof (struct grub_minix_inode), &data->inode); + +diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c +index 3c248a910b42..fc7374ead490 100644 +--- a/grub-core/fs/nilfs2.c ++++ b/grub-core/fs/nilfs2.c +@@ -1,5 +1,5 @@ +-/* +- * nilfs2.c - New Implementation of Log filesystem ++/* ++ * nilfs2.c - New Implementation of Log filesystem + * + * Written by Jiro SEKIBA + * +@@ -680,12 +680,12 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data, + grub_disk_t disk = data->disk; + unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); + +- /* Assume sizeof(struct grub_nilfs2_cpfile_header) < ++ /* Assume sizeof(struct grub_nilfs2_cpfile_header) < + sizeof(struct grub_nilfs2_checkpoint). + */ + blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) / + sizeof (struct grub_nilfs2_checkpoint), &offset); +- ++ + pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1); + if (pptr == (grub_uint64_t) - 1) + { +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 2f34f76da88c..3511e4e2cb6f 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -17,7 +17,7 @@ + * along with this program. If not, see . + */ + +-#define grub_fshelp_node grub_ntfs_file ++#define grub_fshelp_node grub_ntfs_file + + #include + #include +@@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + + static grub_dl_t my_mod; + +-#define grub_fshelp_node grub_ntfs_file ++#define grub_fshelp_node grub_ntfs_file + + static inline grub_uint16_t + u16at (void *ptr, grub_size_t ofs) +@@ -725,7 +725,7 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) + && grub_isalpha (buf[4])) + { + grub_memmove (buf, buf + 6, end - buf + 1 - 6); +- end -= 6; ++ end -= 6; + } + return buf; + } +@@ -992,7 +992,7 @@ grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; +- info.mtime = grub_divmod64 (node->mtime, 10000000, 0) ++ info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); + grub_free (node); +diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c +index b8253da7fed2..42818c376229 100644 +--- a/grub-core/fs/reiserfs.c ++++ b/grub-core/fs/reiserfs.c +@@ -775,7 +775,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, + char *entry_name; + char *entry_name_end = 0; + char c; +- ++ + if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) + continue; + +diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c +index d97b8fbb8c36..1f7dcfca1d3a 100644 +--- a/grub-core/fs/romfs.c ++++ b/grub-core/fs/romfs.c +@@ -112,7 +112,7 @@ grub_romfs_mount (grub_device_t dev) + { + grub_error (GRUB_ERR_BAD_FS, "not romfs"); + return NULL; +- } ++ } + err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ? + sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size)); + if (err) +@@ -271,7 +271,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, + while (1) + { + char buf[16]; +- err = grub_disk_read (dir->data->disk, ++ err = grub_disk_read (dir->data->disk, + laddr >> GRUB_DISK_SECTOR_BITS, + laddr & (GRUB_DISK_SECTOR_SIZE - 1), + 16, buf); +@@ -298,7 +298,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, + node->data_addr = grub_be_to_cpu32 (node->file.spec); + filetype = GRUB_FSHELP_DIR; + } +- ++ + break; + } + } +@@ -402,7 +402,7 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) + data->data->disk->read_hook_data = file->read_hook_data; + grub_disk_read (data->data->disk, + (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS, +- (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), ++ (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), + len, buf); + data->data->disk->read_hook = NULL; + +diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c +index 6dd731e231ee..02b1f9b6d101 100644 +--- a/grub-core/fs/squash4.c ++++ b/grub-core/fs/squash4.c +@@ -210,7 +210,7 @@ struct grub_fshelp_node + struct grub_squash_data *data; + struct grub_squash_inode ino; + grub_size_t stsize; +- struct ++ struct + { + grub_disk_addr_t ino_chunk; + grub_uint16_t ino_offset; +@@ -243,7 +243,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, + csize = SQUASH_CHUNK_SIZE - offset; + if (csize > len) + csize = len; +- ++ + if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) + { + grub_disk_addr_t a = chunk_start + 2 + offset; +@@ -256,7 +256,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, + else + { + char *tmp; +- grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; ++ grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; + grub_disk_addr_t a = chunk_start + 2; + tmp = grub_malloc (bsize); + if (!tmp) +@@ -339,7 +339,7 @@ xz_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + while (len) + { + enum xz_ret xzret; +- ++ + buf.out_pos = 0; + + xzret = xz_dec_run (data->xzdec, &buf); +@@ -399,9 +399,9 @@ squash_mount (grub_disk_t disk) + return NULL; + } + +- err = grub_disk_read (disk, ++ err = grub_disk_read (disk, + grub_le_to_cpu64 (sb.unk1offset) +- >> GRUB_DISK_SECTOR_BITS, ++ >> GRUB_DISK_SECTOR_BITS, + grub_le_to_cpu64 (sb.unk1offset) + & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) +@@ -448,7 +448,7 @@ squash_mount (grub_disk_t disk) + } + + data->blksz = grub_le_to_cpu32 (data->sb.block_size); +- for (data->log2_blksz = 0; ++ for (data->log2_blksz = 0; + (1U << data->log2_blksz) < data->blksz; + data->log2_blksz++); + +@@ -643,7 +643,7 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) + root->stack[0].ino_chunk = grub_le_to_cpu32 (data->sb.root_ino_chunk); + root->stack[0].ino_offset = grub_cpu_to_le16 (data->sb.root_ino_offset); + return read_chunk (data, &root->ino, sizeof (root->ino), +- grub_le_to_cpu64 (data->sb.inodeoffset) ++ grub_le_to_cpu64 (data->sb.inodeoffset) + + root->stack[0].ino_chunk, + root->stack[0].ino_offset); + } +@@ -765,7 +765,7 @@ grub_squash_open (struct grub_file *file, const char *name) + } + + static grub_ssize_t +-direct_read (struct grub_squash_data *data, ++direct_read (struct grub_squash_data *data, + struct grub_squash_cache_inode *ino, + grub_off_t off, char *buf, grub_size_t len) + { +@@ -882,7 +882,7 @@ direct_read (struct grub_squash_data *data, + grub_free (block); + } + else +- err = grub_disk_read (data->disk, ++ err = grub_disk_read (data->disk, + (ino->cumulated_block_sizes[i] + a + boff) + >> GRUB_DISK_SECTOR_BITS, + (ino->cumulated_block_sizes[i] + a + boff) +@@ -946,7 +946,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) + } + else + off -= direct_len; +- ++ + err = read_chunk (data, &frag, sizeof (frag), + data->fragments, sizeof (frag) * fragment); + if (err) +@@ -957,7 +957,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) + b = grub_le_to_cpu32 (ino->ino.long_file.offset) + off; + else + b = grub_le_to_cpu32 (ino->ino.file.offset) + off; +- ++ + /* FIXME: cache uncompressed chunks. */ + if (compressed) + { +@@ -1013,7 +1013,7 @@ grub_squash_mtime (grub_device_t dev, grub_int64_t *tm) + *tm = grub_le_to_cpu32 (data->sb.creation_time); + squash_unmount (data); + return GRUB_ERR_NONE; +-} ++} + + static struct grub_fs grub_squash_fs = + { +diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c +index 2ac5c1d0048f..5a665093ed77 100644 +--- a/grub-core/fs/udf.c ++++ b/grub-core/fs/udf.c +@@ -567,7 +567,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + (buf + sizeof (struct grub_udf_aed)); + continue; + } +- ++ + if (filebytes < adlen) + { + grub_uint32_t ad_block_num = ad->block.block_num; +diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c +index 34a698b71b8d..a354c92d936a 100644 +--- a/grub-core/fs/ufs.c ++++ b/grub-core/fs/ufs.c +@@ -568,7 +568,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) + { + dirino = data->ino; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0); +- ++ + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_LNK) + { +@@ -613,7 +613,7 @@ grub_ufs_mount (grub_disk_t disk) + && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0) + && data->sblock.ino_per_group != 0) + { +- for (data->log2_blksz = 0; ++ for (data->log2_blksz = 0; + (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize); + data->log2_blksz++); + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index e3816d1ec4a9..d6de7f1a2dd2 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -894,7 +894,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + tag, which is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; + +- if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), ++ if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), + filename, &ctx)) + { + grub_free (dirblock); +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index cf4d2ab189a5..5961818abc9a 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -176,7 +176,7 @@ typedef struct decomp_entry + /* + * Signature for checksum functions. + */ +-typedef void zio_checksum_t(const void *data, grub_uint64_t size, ++typedef void zio_checksum_t(const void *data, grub_uint64_t size, + grub_zfs_endian_t endian, zio_cksum_t *zcp); + + /* +@@ -297,7 +297,7 @@ check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) + static grub_err_t + check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); + +-static grub_err_t ++static grub_err_t + zlib_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) + { +@@ -310,7 +310,7 @@ zlib_decompress (void *s, void *d, + return grub_errno; + } + +-static grub_err_t ++static grub_err_t + zle_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) + { +@@ -415,7 +415,7 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { + */ + static grub_err_t + zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, +- grub_zfs_endian_t endian, ++ grub_zfs_endian_t endian, + char *buf, grub_size_t size) + { + zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1; +@@ -425,14 +425,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, + if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func == NULL) + { + grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unknown checksum function %d", checksum); + } + + if (ci->ci_eck) + { +- expected_cksum = zec->zec_cksum; +- zec->zec_cksum = zc; ++ expected_cksum = zec->zec_cksum; ++ zec->zec_cksum = zc; + ci->ci_func (buf, size, endian, &actual_cksum); + zec->zec_cksum = expected_cksum; + zc = expected_cksum; +@@ -445,14 +445,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, + { + grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); + grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", +- (unsigned long long) actual_cksum.zc_word[0], ++ (unsigned long long) actual_cksum.zc_word[0], + (unsigned long long) actual_cksum.zc_word[1], +- (unsigned long long) actual_cksum.zc_word[2], ++ (unsigned long long) actual_cksum.zc_word[2], + (unsigned long long) actual_cksum.zc_word[3]); + grub_dprintf ("zfs", "expected checksum %016llx %016llx %016llx %016llx\n", +- (unsigned long long) zc.zc_word[0], ++ (unsigned long long) zc.zc_word[0], + (unsigned long long) zc.zc_word[1], +- (unsigned long long) zc.zc_word[2], ++ (unsigned long long) zc.zc_word[2], + (unsigned long long) zc.zc_word[3]); + return grub_error (GRUB_ERR_BAD_FS, N_("checksum verification failed")); + } +@@ -485,17 +485,17 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) + else + ub2_endian = GRUB_ZFS_BIG_ENDIAN; + +- if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + return -1; +- if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + return 1; + +- if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + return -1; +- if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) ++ if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + return 1; + +@@ -573,7 +573,7 @@ find_bestub (uberblock_phys_t * ub_array, + grub_errno = GRUB_ERR_NONE; + continue; + } +- if (ubbest == NULL ++ if (ubbest == NULL + || vdev_uberblock_compare (&(ubptr->ubp_uberblock), + &(ubbest->ubp_uberblock)) > 0) + ubbest = ubptr; +@@ -594,10 +594,10 @@ get_psize (blkptr_t * bp, grub_zfs_endian_t endian) + static grub_uint64_t + dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian) + { +- grub_dprintf ("zfs", "dva=%llx, %llx\n", +- (unsigned long long) dva->dva_word[0], ++ grub_dprintf ("zfs", "dva=%llx, %llx\n", ++ (unsigned long long) dva->dva_word[0], + (unsigned long long) dva->dva_word[1]); +- return grub_zfs_to_cpu64 ((dva)->dva_word[1], ++ return grub_zfs_to_cpu64 ((dva)->dva_word[1], + endian) << SPA_MINBLOCKSHIFT; + } + +@@ -720,7 +720,7 @@ fill_vdev_info_real (struct grub_zfs_data *data, + if (!fill->children) + { + fill->n_children = nelm; +- ++ + fill->children = grub_zalloc (fill->n_children + * sizeof (fill->children[0])); + } +@@ -839,7 +839,7 @@ nvlist_next_nvpair (const char *nvl, const char *nvpair) + { + /* skip over header, nvl_version and nvl_nvflag */ + nvpair = nvl + 4 * 3; +- } ++ } + else + { + /* skip to the next nvpair */ +@@ -873,10 +873,10 @@ nvlist_next_nvpair (const char *nvl, const char *nvpair) + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + +- nvp = nvp + ((name_len + 3) & ~3); // align +- if (nvp + 4 >= nvl + VDEV_PHYS_SIZE ++ nvp = nvp + ((name_len + 3) & ~3); // align ++ if (nvp + 4 >= nvl + VDEV_PHYS_SIZE + || encode_size < 0 +- || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) ++ || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); +@@ -896,7 +896,7 @@ nvpair_name (const char *nvp, char **buf, grub_size_t *buflen) + { + /* skip over encode/decode size */ + nvp += 4 * 2; +- ++ + *buf = (char *) (nvp + 4); + *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + +@@ -943,7 +943,7 @@ nvpair_value (const char *nvp,char **val, + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ +- ++ + /* skip over type */ + nvp += 4; + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); +@@ -957,7 +957,7 @@ nvpair_value (const char *nvp,char **val, + *size_out = encode_size; + if (nelm_out) + *nelm_out = nelm; +- ++ + return 1; + } + +@@ -1183,7 +1183,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, + desc.vdev_phys_sector + = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) +- + (label < VDEV_LABELS / 2 ? 0 : ++ + (label < VDEV_LABELS / 2 ? 0 : + ALIGN_DOWN (grub_disk_native_sectors (dev->disk), sizeof (vdev_label_t)) + - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); + +@@ -1229,7 +1229,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, + grub_free (bh); + return GRUB_ERR_NONE; + } +- ++ + grub_free (ub_array); + grub_free (bh); + +@@ -1269,7 +1269,7 @@ scan_devices_iter (const char *name, void *hook_data) + + if (!inserted) + grub_device_close (dev); +- ++ + return 0; + } + +@@ -1386,7 +1386,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, + for (i = 0; i < nbufs; i++) + { + grub_uint8_t mul; +- for (j = i; j < nbufs; j++) ++ for (j = i; j < nbufs; j++) + if (matrix1[i][j]) + break; + if (j == nbufs) +@@ -1453,7 +1453,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, + } + default: + return grub_error (GRUB_ERR_BUG, "too big matrix"); +- } ++ } + } + + static grub_err_t +@@ -1510,7 +1510,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, + int idx, orig_idx; + + if (desc->nparity < 1 || desc->nparity > 3) +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "raidz%d is not supported", desc->nparity); + + if (desc->n_children <= desc->nparity || desc->n_children < 1) +@@ -1659,7 +1659,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, + len -= csize; + idx--; + } +- for (i = 0; i < failed_devices ++ for (i = 0; i < failed_devices + && recovery_len[i] == recovery_len[0]; + i++); + /* Since the chunks have variable length handle the last block +@@ -1782,7 +1782,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, + * Read in a block of raw data to buf. + */ + static grub_err_t +-zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, ++zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, + struct grub_zfs_data *data) + { + int i, psize; +@@ -1850,7 +1850,7 @@ decode_embedded_bp_compressed(const blkptr_t *bp, void *buf) + * and put the uncompressed data in buf. + */ + static grub_err_t +-zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, ++zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + grub_size_t *size, struct grub_zfs_data *data) + { + grub_size_t lsize, psize; +@@ -1936,7 +1936,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + if (encrypted) + { + if (!grub_zfs_decrypt) +- err = grub_error (GRUB_ERR_BAD_FS, ++ err = grub_error (GRUB_ERR_BAD_FS, + N_("module `%s' isn't loaded"), + "zfscrypt"); + else +@@ -1960,7 +1960,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + endian)); + return grub_error (GRUB_ERR_BAD_FS, "no key found in keychain"); + } +- grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T ++ grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T + ", %p) for txg %" PRIxGRUB_UINT64_T "\n", + besti, data->subvol.keyring[besti].txg, + data->subvol.keyring[besti].cipher, +@@ -2008,7 +2008,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, + * + */ + static grub_err_t +-dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, ++dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, + grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) + { + int level; +@@ -2038,8 +2038,8 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, + + if (BP_IS_HOLE (bp)) + { +- grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, +- dn->endian) ++ grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, ++ dn->endian) + << SPA_MINBLOCKSHIFT; + *buf = grub_malloc (size); + if (!*buf) +@@ -2103,7 +2103,7 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, + } + + static int +-mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, ++mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_dir_ctx *ctx) +@@ -2117,7 +2117,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, + grub_dprintf ("zfs", "zap: name = %s, value = %llx, cd = %x\n", + mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value, + (int)mzap_ent[i].mze_cd); +- if (hook (mzap_ent[i].mze_name, ++ if (hook (mzap_ent[i].mze_name, + grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx)) + return 1; + } +@@ -2178,12 +2178,12 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, + + if (!case_insensitive) + return grub_memcmp (t1, t2, n); +- ++ + while (n--) + { + if (grub_toupper (*t1) != grub_toupper (*t2)) + return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); +- ++ + t1++; + t2++; + } +@@ -2221,7 +2221,7 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, + + /* XXX */ + static grub_err_t +-zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, ++zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, + int chunk, grub_size_t array_len, char *buf) + { + grub_size_t bseen = 0; +@@ -2285,7 +2285,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, + + grub_dprintf ("zfs", "fzap: length %d\n", (int) le->le_name_length); + +- if (zap_leaf_array_equal (l, endian, blksft, ++ if (zap_leaf_array_equal (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_name_chunk,endian), + grub_zfs_to_cpu16 (le->le_name_length, endian), + name, case_insensitive)) +@@ -2334,7 +2334,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, + { + void *l; + grub_uint64_t hash, idx, blkid; +- int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, ++ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + zap_dnode->endian) << DNODE_SHIFT); + grub_err_t err; + grub_zfs_endian_t leafendian; +@@ -2347,7 +2347,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, + + /* get block id from index */ + if (zap->zap_ptrtbl.zt_numblks != 0) +- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "external pointer tables not supported"); + idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); + blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], zap_dnode->endian); +@@ -2379,7 +2379,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, + void *l_in; + grub_uint64_t idx, idx2, blkid; + grub_uint16_t chunk; +- int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, ++ int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + zap_dnode->endian) << DNODE_SHIFT); + grub_err_t err; + grub_zfs_endian_t endian; +@@ -2390,7 +2390,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, + /* get block id from index */ + if (zap->zap_ptrtbl.zt_numblks != 0) + { +- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "external pointer tables not supported"); + return 0; + } +@@ -2517,7 +2517,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, + grub_dprintf ("zfs", "micro zap\n"); + err = mzap_lookup (zapbuf, endian, size, name, val, + case_insensitive); +- grub_dprintf ("zfs", "returned %d\n", err); ++ grub_dprintf ("zfs", "returned %d\n", err); + grub_free (zapbuf); + return err; + } +@@ -2527,7 +2527,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, + /* this is a fat zap */ + err = fzap_lookup (zap_dnode, zapbuf, name, val, data, + case_insensitive); +- grub_dprintf ("zfs", "returned %d\n", err); ++ grub_dprintf ("zfs", "returned %d\n", err); + grub_free (zapbuf); + return err; + } +@@ -2560,7 +2560,7 @@ zap_iterate_u64_transform (const void *name, + } + + static int +-zap_iterate_u64 (dnode_end_t * zap_dnode, ++zap_iterate_u64 (dnode_end_t * zap_dnode, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx) +@@ -2607,7 +2607,7 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, + } + + static int +-zap_iterate (dnode_end_t * zap_dnode, ++zap_iterate (dnode_end_t * zap_dnode, + grub_size_t nameelemlen, + int (*hook) (const void *name, grub_size_t namelen, + const void *val_in, +@@ -2667,7 +2667,7 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + grub_err_t err; + grub_zfs_endian_t endian; + +- blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, ++ blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, + mdn->endian) << SPA_MINBLOCKSHIFT; + epbs = zfs_log2 (blksz) - DNODE_SHIFT; + +@@ -2678,18 +2678,18 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + blkid = objnum >> epbs; + idx = objnum & ((1 << epbs) - 1); + +- if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, +- sizeof (*mdn)) == 0 ++ if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, ++ sizeof (*mdn)) == 0 + && objnum >= data->dnode_start && objnum < data->dnode_end) + { + grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE); + buf->endian = data->dnode_endian; +- if (type && buf->dn.dn_type != type) +- return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); ++ if (type && buf->dn.dn_type != type) ++ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + return GRUB_ERR_NONE; + } + +- grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, ++ grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, + (unsigned long long) blkid); + err = dmu_read (mdn, blkid, &dnbuf, &endian, data); + if (err) +@@ -2715,8 +2715,8 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + + grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE); + buf->endian = endian; +- if (type && buf->dn.dn_type != type) +- return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); ++ if (type && buf->dn.dn_type != type) ++ return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + + return GRUB_ERR_NONE; + } +@@ -2740,7 +2740,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + struct dnode_chain + { + struct dnode_chain *next; +- dnode_end_t dn; ++ dnode_end_t dn; + }; + struct dnode_chain *dnode_path = 0, *dn_new, *root; + +@@ -2750,7 +2750,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + dn_new->next = 0; + dnode_path = root = dn_new; + +- err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, ++ err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + &(dnode_path->dn), data); + if (err) + { +@@ -2801,7 +2801,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + grub_free (dn_new); + return grub_errno; + } +- ++ + while (1) + { + /* skip leading slashes */ +@@ -2827,7 +2827,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + } + else + { +- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "can't resolve .."); + break; + } +@@ -2877,7 +2877,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + { + grub_size_t block; + grub_size_t blksz; +- blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, ++ blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, + dnode_path->dn.endian) + << SPA_MINBLOCKSHIFT); + +@@ -2916,7 +2916,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + if (err) + break; + free_symval = 1; +- } ++ } + path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); + if (!path_buf) + { +@@ -2930,9 +2930,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + if (free_symval) + grub_free (sym_value); + path [sym_sz] = 0; +- grub_memcpy (path + grub_strlen (path), oldpath, ++ grub_memcpy (path + grub_strlen (path), oldpath, + grub_strlen (oldpath) + 1); +- ++ + grub_free (oldpathbuf); + if (path[0] != '/') + { +@@ -2951,7 +2951,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + { + void *sahdrp; + int hdrsize; +- ++ + if (dnode_path->dn.dn.dn_bonuslen != 0) + { + sahdrp = DN_BONUS (&dnode_path->dn.dn); +@@ -2959,7 +2959,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dnode_path->dn.dn.dn_spill; +- ++ + err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); + if (err) + break; +@@ -2978,7 +2978,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + { + char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; +- grub_size_t sym_sz = ++ grub_size_t sym_sz = + grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_SIZE_OFFSET), +@@ -2993,9 +2993,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + } + grub_memcpy (path, sym_value, sym_sz); + path [sym_sz] = 0; +- grub_memcpy (path + grub_strlen (path), oldpath, ++ grub_memcpy (path + grub_strlen (path), oldpath, + grub_strlen (oldpath) + 1); +- ++ + grub_free (oldpathbuf); + if (path[0] != '/') + { +@@ -3096,7 +3096,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, + + grub_dprintf ("zfs", "endian = %d\n", mosmdn->endian); + +- err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, ++ err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, + DMU_OT_OBJECT_DIRECTORY, mdn, data); + if (err) + return err; +@@ -3119,7 +3119,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, + { + grub_uint64_t childobj; + char *cname, ch; +- ++ + while (*fsname == '/') + fsname++; + +@@ -3279,7 +3279,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + filename = ptr_slash; + else + filename = "/"; +- grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", ++ grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", + fsname, snapname, filename); + } + grub_dprintf ("zfs", "alive\n"); +@@ -3365,7 +3365,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + + snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian); + +- err = dnode_get (&(data->mos), snapobj, ++ err = dnode_get (&(data->mos), snapobj, + DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data); + if (!err) + err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0); +@@ -3383,13 +3383,13 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + subvol->obj = headobj; + + make_mdn (&subvol->mdn, data); +- ++ + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); + + if (*isfs) + { + grub_free (fsname); +- grub_free (snapname); ++ grub_free (snapname); + return GRUB_ERR_NONE; + } + err = dnode_get_path (subvol, filename, dn, data); +@@ -3409,9 +3409,9 @@ nvlist_find_value (const char *nvlist_in, const char *name, + char *nvp_name; + + /* Verify if the 1st and 2nd byte in the nvlist are valid. */ +- /* NOTE: independently of what endianness header announces all ++ /* NOTE: independently of what endianness header announces all + subsequent values are big-endian. */ +- if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN ++ if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN + && nvlist[1] != NV_BIG_ENDIAN)) + { + grub_dprintf ("zfs", "incorrect nvlist header\n"); +@@ -3532,13 +3532,13 @@ get_nvlist_size (const char *beg, const char *limit) + { + const char *ptr; + grub_uint32_t encode_size; +- ++ + ptr = beg + 8; + + while (ptr < limit + && (encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (ptr)))) + ptr += encode_size; /* goto the next nvpair */ +- ptr += 8; ++ ptr += 8; + return (ptr > limit) ? -1 : (ptr - beg); + } + +@@ -3674,8 +3674,8 @@ zfs_mount (grub_device_t dev) + } + + ub = &(data->current_uberblock); +- ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, +- GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ++ ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, ++ GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); + + err = zio_read (&ub->ub_rootbp, ub_endian, +@@ -3728,7 +3728,7 @@ grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist) + return err; + } + +-static grub_err_t ++static grub_err_t + zfs_label (grub_device_t device, char **label) + { + char *nvlist; +@@ -3740,7 +3740,7 @@ zfs_label (grub_device_t device, char **label) + return grub_errno; + + err = zfs_fetch_nvlist (data->device_original, &nvlist); +- if (err) ++ if (err) + { + zfs_unmount (data); + return err; +@@ -3752,7 +3752,7 @@ zfs_label (grub_device_t device, char **label) + return grub_errno; + } + +-static grub_err_t ++static grub_err_t + zfs_uuid (grub_device_t device, char **uuid) + { + struct grub_zfs_data *data; +@@ -3770,7 +3770,7 @@ zfs_uuid (grub_device_t device, char **uuid) + return GRUB_ERR_NONE; + } + +-static grub_err_t ++static grub_err_t + zfs_mtime (grub_device_t device, grub_int64_t *mt) + { + struct grub_zfs_data *data; +@@ -3784,8 +3784,8 @@ zfs_mtime (grub_device_t device, grub_int64_t *mt) + return grub_errno; + + ub = &(data->current_uberblock); +- ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, +- GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ++ ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, ++ GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); + + *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); +@@ -3823,7 +3823,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) + } + + /* We found the dnode for this file. Verify if it is a plain file. */ +- if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) ++ if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) + { + zfs_unmount (data); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); +@@ -3898,7 +3898,7 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) + return len; + } + +- blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, ++ blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, + data->dnode.endian) << SPA_MINBLOCKSHIFT; + + if (blksz == 0) +@@ -3991,11 +3991,11 @@ fill_fs_info (struct grub_dirhook_info *info, + dnode_end_t dn; + grub_uint64_t objnum; + grub_uint64_t headobj; +- ++ + grub_memset (info, 0, sizeof (*info)); +- ++ + info->dir = 1; +- ++ + if (mdn.dn.dn_type == DMU_OT_DSL_DIR) + { + headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); +@@ -4010,28 +4010,28 @@ fill_fs_info (struct grub_dirhook_info *info, + err = make_mdn (&mdn, data); + if (err) + return err; +- err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, ++ err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + &dn, data); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + err = dnode_get (&mdn, objnum, 0, &dn, data); + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } +- ++ + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; +@@ -4117,15 +4117,15 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.case_insensitive = ctx->data->subvol.case_insensitive; + } +- ++ + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) +- { ++ { + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], + dn.endian); + } + info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); +- grub_dprintf ("zfs", "type=%d, name=%s\n", ++ grub_dprintf ("zfs", "type=%d, name=%s\n", + (int)dn.dn.dn_type, (char *)name); + return ctx->hook (name, &info, ctx->hook_data); + } +@@ -4219,7 +4219,7 @@ grub_zfs_dir (grub_device_t device, const char *path, + + if (isfs) + { +- grub_uint64_t childobj, headobj; ++ grub_uint64_t childobj, headobj; + grub_uint64_t snapobj; + dnode_end_t dn; + struct grub_dirhook_info info; +@@ -4247,7 +4247,7 @@ grub_zfs_dir (grub_device_t device, const char *path, + } + + zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); +- ++ + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); + if (err) + { +@@ -4289,8 +4289,8 @@ check_feature (const char *name, grub_uint64_t val, + return 0; + if (name[0] == 0) + return 0; +- for (i = 0; spa_feature_names[i] != NULL; i++) +- if (grub_strcmp (name, spa_feature_names[i]) == 0) ++ for (i = 0; spa_feature_names[i] != NULL; i++) ++ if (grub_strcmp (name, spa_feature_names[i]) == 0) + return 0; + return 1; + } +@@ -4303,7 +4303,7 @@ check_feature (const char *name, grub_uint64_t val, + * 0: Success. + * errnum: Failure. + */ +- ++ + static grub_err_t + check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) + { +@@ -4328,7 +4328,7 @@ check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct gru + errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0); + if (errnum != 0) + return errnum; +- ++ + errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data); + if (errnum != 0) + return errnum; +diff --git a/grub-core/fs/zfs/zfs_fletcher.c b/grub-core/fs/zfs/zfs_fletcher.c +index 7d27b053dc7a..ad3be6705479 100644 +--- a/grub-core/fs/zfs/zfs_fletcher.c ++++ b/grub-core/fs/zfs/zfs_fletcher.c +@@ -39,14 +39,14 @@ + #include + + void +-fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, ++fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + zio_cksum_t *zcp) + { + const grub_uint64_t *ip = buf; + const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t)); + grub_uint64_t a0, b0, a1, b1; +- +- for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) ++ ++ for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) + { + a0 += grub_zfs_to_cpu64 (ip[0], endian); + a1 += grub_zfs_to_cpu64 (ip[1], endian); +@@ -61,14 +61,14 @@ fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + } + + void +-fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, ++fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, + zio_cksum_t *zcp) + { + const grub_uint32_t *ip = buf; + const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t)); + grub_uint64_t a, b, c, d; +- +- for (a = b = c = d = 0; ip < ipend; ip++) ++ ++ for (a = b = c = d = 0; ip < ipend; ip++) + { + a += grub_zfs_to_cpu32 (ip[0], endian);; + b += a; +diff --git a/grub-core/fs/zfs/zfs_sha256.c b/grub-core/fs/zfs/zfs_sha256.c +index a181f076c54c..f042fa61ab89 100644 +--- a/grub-core/fs/zfs/zfs_sha256.c ++++ b/grub-core/fs/zfs/zfs_sha256.c +@@ -116,23 +116,23 @@ zio_checksum_SHA256(const void *buf, grub_uint64_t size, + grub_uint8_t pad[128]; + unsigned padsize = size & 63; + unsigned i; +- ++ + for (i = 0; i < size - padsize; i += 64) + SHA256Transform(H, (grub_uint8_t *)buf + i); +- ++ + for (i = 0; i < padsize; i++) + pad[i] = ((grub_uint8_t *)buf)[i]; +- ++ + for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++) + pad[padsize] = 0; +- ++ + for (i = 0; i < 8; i++) + pad[padsize++] = (size << 3) >> (56 - 8 * i); +- ++ + for (i = 0; i < padsize && i <= 64; i += 64) + SHA256Transform(H, pad + i); +- +- zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], ++ ++ zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], + endian); + zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3], + endian); +diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c +index de3b015f5827..da30e9ab33dd 100644 +--- a/grub-core/fs/zfs/zfscrypt.c ++++ b/grub-core/fs/zfs/zfscrypt.c +@@ -46,7 +46,7 @@ + GRUB_MOD_LICENSE ("GPLv3+"); + + /* +- Mostly based on following article: ++ Mostly based on following article: + https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on + */ + +@@ -179,7 +179,7 @@ grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b) + grub_crypto_xor (res, res, bs, 16); + grub_gcm_mul_x (bs); + } +- ++ + grub_memcpy (a, res, 16); + } + +@@ -275,7 +275,7 @@ algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, + } + + static grub_err_t +-grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, ++grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + grub_uint64_t algo, + void *nonce, + char *buf, grub_size_t size, +@@ -286,7 +286,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + unsigned i; + grub_uint32_t sw[4]; + gcry_err_code_t err; +- ++ + grub_memcpy (sw, nonce, 16); + if (endian != GRUB_ZFS_BIG_ENDIAN) + for (i = 0; i < 4; i++) +@@ -302,7 +302,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + sw + 1, 3, 12); + if (err) + return grub_crypto_gcry_error (err); +- ++ + for (i = 0; i < 3; i++) + if (grub_zfs_to_cpu32 (expected_mac[i], endian) + != grub_be_to_cpu32 (mac[i])) +@@ -362,7 +362,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, + grub_crypto_cipher_close (cipher); + continue; + } +- ++ + err = grub_crypto_cipher_set_key (cipher, wrap_key_real, + keylen); + if (err) +@@ -371,7 +371,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, + grub_crypto_cipher_close (cipher); + continue; + } +- ++ + err = algo_decrypt (cipher, algo, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); + if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) diff --git a/0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch b/0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch new file mode 100644 index 00000000..f5421ce3 --- /dev/null +++ b/0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "t.feng" +Date: Tue, 29 Nov 2022 17:14:15 +0800 +Subject: [PATCH] fs/xfs: Fix memory leaks in XFS module + +Signed-off-by: t.feng +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index d6de7f1a2dd2..b67407690c1a 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -585,7 +585,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + if (grub_disk_read (node->data->disk, + GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 0, node->data->bsize, leaf)) +- return 0; ++ { ++ grub_free (leaf); ++ return 0; ++ } + + if ((!node->data->hascrc && + grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || +@@ -751,6 +754,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + if (err) + { + grub_print_error (); ++ grub_free (fdiro); + return 0; + } + +@@ -861,7 +865,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + blk << dirblk_log2, + dirblk_size, dirblock, 0); + if (numread != dirblk_size) +- return 0; ++ { ++ grub_free (dirblock); ++ return 0; ++ } + + entries = (grub_be_to_cpu32 (tail->leaf_count) + - grub_be_to_cpu32 (tail->leaf_stale)); diff --git a/0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch b/0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch new file mode 100644 index 00000000..7083a57b --- /dev/null +++ b/0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darren Kenny +Date: Fri, 2 Jun 2023 18:08:44 +0000 +Subject: [PATCH] fs/xfs: Fix issues found while fuzzing the XFS filesystem + +While performing fuzz testing with XFS filesystem images with ASAN +enabled, several issues were found where the memory accesses are made +beyond the data that is allocated into the struct grub_xfs_data +structure's data field. + +The existing structure didn't store the size of the memory allocated into +the buffer in the data field and had no way to check it. To resolve these +issues, the data size is stored to enable checks into the data buffer. + +With these checks in place, the fuzzing corpus no longer cause any crashes. + +Signed-off-by: Darren Kenny +Signed-off-by: Robbie Harwood +Signed-off-by: Marta Lewandowska +Signed-off-by: Lidong Chen +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index b67407690c1a..b91cd32b49ab 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -239,6 +239,7 @@ struct grub_fshelp_node + + struct grub_xfs_data + { ++ grub_size_t data_size; + struct grub_xfs_sblock sblock; + grub_disk_t disk; + int pos; +@@ -611,8 +612,20 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + } + else if (node->inode.format == XFS_INODE_FORMAT_EXT) + { ++ grub_addr_t exts_end = 0; ++ grub_addr_t data_end = 0; ++ + nrec = grub_be_to_cpu32 (node->inode.nextents); + exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); ++ ++ if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) || ++ grub_add ((grub_addr_t) node->data, exts_end, &exts_end) || ++ grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) || ++ exts_end > data_end) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS extents"); ++ return 0; ++ } + } + else + { +@@ -803,6 +816,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); + grub_uint8_t c; + ++ if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)) ++ return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode"); ++ + /* inopos might be unaligned. */ + if (smallino) + ino = (((grub_uint32_t) inopos[0]) << 24) +@@ -829,6 +845,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + de->name[de->len] = c; + + de = grub_xfs_inline_next_de(dir->data, head, de); ++ ++ if ((grub_uint8_t *) de >= (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)) ++ return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); ++ + } + break; + } +@@ -897,6 +917,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + } + + filename = (char *)(direntry + 1); ++ if (filename + direntry->len - 1 > (char *) tail) ++ return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); ++ + /* The byte after the filename is for the filetype, padding, or + tag, which is not used by GRUB. So it can be overwritten. */ + filename[direntry->len] = '\0'; +@@ -941,6 +964,8 @@ grub_xfs_mount (grub_disk_t disk) + if (!data) + return 0; + ++ data->data_size = sizeof (struct grub_xfs_data); ++ + grub_dprintf("xfs", "Reading sb\n"); + /* Read the superblock. */ + if (grub_disk_read (disk, 0, 0, +@@ -962,6 +987,7 @@ grub_xfs_mount (grub_disk_t disk) + if (! data) + goto fail; + ++ data->data_size = sz; + data->diropen.data = data; + data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino); + data->diropen.inode_read = 1; diff --git a/0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch b/0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch new file mode 100644 index 00000000..d70ec5ad --- /dev/null +++ b/0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lidong Chen +Date: Thu, 28 Sep 2023 22:33:44 +0000 +Subject: [PATCH] fs/xfs: Incorrect short form directory data boundary check + +After parsing of the current entry, the entry pointer is advanced +to the next entry at the end of the "for" loop. In case where the +last entry is at the end of the data boundary, the advanced entry +pointer can point off the data boundary. The subsequent boundary +check for the advanced entry pointer can cause a failure. + +The fix is to include the boundary check into the "for" loop +condition. + +Signed-off-by: Lidong Chen +Reviewed-by: Daniel Kiper +Tested-by: Sebastian Andrzej Siewior +Tested-by: Marta Lewandowska +--- + grub-core/fs/xfs.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index b91cd32b49ab..ebf962793fa7 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -810,7 +810,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + if (iterate_dir_call_hook (parent, "..", &ctx)) + return 1; + +- for (i = 0; i < head->count; i++) ++ for (i = 0; i < head->count && ++ (grub_uint8_t *) de < ((grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)); i++) + { + grub_uint64_t ino; + grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); +@@ -845,10 +846,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + de->name[de->len] = c; + + de = grub_xfs_inline_next_de(dir->data, head, de); +- +- if ((grub_uint8_t *) de >= (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)) +- return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); +- + } + break; + } diff --git a/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch b/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch new file mode 100644 index 00000000..c0057310 --- /dev/null +++ b/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jon DeVree +Date: Tue, 17 Oct 2023 23:03:47 -0400 +Subject: [PATCH] fs/xfs: Fix XFS directory extent parsing + +The XFS directory entry parsing code has never been completely correct +for extent based directories. The parser correctly handles the case +where the directory is contained in a single extent, but then mistakenly +assumes the data blocks for the multiple extent case are each identical +to the single extent case. The difference in the format of the data +blocks between the two cases is tiny enough that its gone unnoticed for +a very long time. + +A recent change introduced some additional bounds checking into the XFS +parser. Like GRUB's existing parser, it is correct for the single extent +case but incorrect for the multiple extent case. When parsing a directory +with multiple extents, this new bounds checking is sometimes (but not +always) tripped and triggers an "invalid XFS directory entry" error. This +probably would have continued to go unnoticed but the /boot/grub/ +directory is large enough that it often has multiple extents. + +The difference between the two cases is that when there are multiple +extents, the data blocks do not contain a trailer nor do they contain +any leaf information. That information is stored in a separate set of +extents dedicated to just the leaf information. These extents come after +the directory entry extents and are not included in the inode size. So +the existing parser already ignores the leaf extents. + +The only reason to read the trailer/leaf information at all is so that +the parser can avoid misinterpreting that data as directory entries. So +this updates the parser as follows: + +For the single extent case the parser doesn't change much: +1. Read the size of the leaf information from the trailer +2. Set the end pointer for the parser to the start of the leaf + information. (The previous bounds checking set the end pointer to the + start of the trailer, so this is actually a small improvement.) +3. Set the entries variable to the expected number of directory entries. + +For the multiple extent case: +1. Set the end pointer to the end of the block. +2. Do not set up the entries variable. Figuring out how many entries are + in each individual block is complex and does not seem worth it when + it appears to be safe to just iterate over the entire block. + +The bounds check itself was also dependent upon the faulty XFS parser +because it accidentally used "filename + length - 1". Presumably this +was able to pass the fuzzer because in the old parser there was always +8 bytes of slack space between the tail pointer and the actual end of +the block. Since this is no longer the case the bounds check needs to be +updated to "filename + length + 1" in order to prevent a regression in +the handling of corrupt fliesystems. + +Notes: +* When there is only one extent there will only ever be one block. If + more than one block is required then XFS will always switch to holding + leaf information in a separate extent. +* B-tree based directories seems to be parsed properly by the same code + that handles multiple extents. This is unlikely to ever occur within + /boot though because its only used when there are an extremely large + number of directory entries. + +Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem) +Fixes: b2499b29c (Adds support for the XFS filesystem.) +Fixes: https://savannah.gnu.org/bugs/?64376 + +Signed-off-by: Jon DeVree +Reviewed-by: Daniel Kiper +Tested-by: Sebastian Andrzej Siewior +Tested-by: Marta Lewandowska +--- + grub-core/fs/xfs.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 38 insertions(+), 14 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index ebf962793fa7..18edfcff486c 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -223,6 +223,12 @@ struct grub_xfs_inode + /* Size of struct grub_xfs_inode v2, up to unused4 member included. */ + #define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + ++struct grub_xfs_dir_leaf_entry ++{ ++ grub_uint32_t hashval; ++ grub_uint32_t address; ++} GRUB_PACKED; ++ + struct grub_xfs_dirblock_tail + { + grub_uint32_t leaf_count; +@@ -874,9 +880,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + { + struct grub_xfs_dir2_entry *direntry = + grub_xfs_first_de(dir->data, dirblock); +- int entries; +- struct grub_xfs_dirblock_tail *tail = +- grub_xfs_dir_tail(dir->data, dirblock); ++ int entries = -1; ++ char *end = dirblock + dirblk_size; + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -887,14 +892,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 0; + } + +- entries = (grub_be_to_cpu32 (tail->leaf_count) +- - grub_be_to_cpu32 (tail->leaf_stale)); ++ /* ++ * Leaf and tail information are only in the data block if the number ++ * of extents is 1. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); + +- if (!entries) +- continue; ++ end = (char *) tail; ++ ++ /* Subtract the space used by leaf nodes. */ ++ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry); ++ ++ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale); ++ ++ if (!entries) ++ continue; ++ } + + /* Iterate over all entries within this block. */ +- while ((char *)direntry < (char *)tail) ++ while ((char *) direntry < (char *) end) + { + grub_uint8_t *freetag; + char *filename; +@@ -914,7 +932,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + } + + filename = (char *)(direntry + 1); +- if (filename + direntry->len - 1 > (char *) tail) ++ if (filename + direntry->len + 1 > (char *) end) + return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); + + /* The byte after the filename is for the filetype, padding, or +@@ -928,11 +946,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 1; + } + +- /* Check if last direntry in this block is +- reached. */ +- entries--; +- if (!entries) +- break; ++ /* ++ * The expected number of directory entries is only tracked for the ++ * single extent case. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ /* Check if last direntry in this block is reached. */ ++ entries--; ++ if (!entries) ++ break; ++ } + + /* Select the next directory entry. */ + direntry = grub_xfs_next_de(dir->data, direntry); diff --git a/0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch b/0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch new file mode 100644 index 00000000..8c414a8e --- /dev/null +++ b/0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Anthony Iliopoulos +Date: Thu, 26 Oct 2023 11:53:39 +0200 +Subject: [PATCH] fs/xfs: Add large extent counters incompat feature support + +XFS introduced 64-bit extent counters for inodes via a series of +upstream commits and the feature was marked as stable in v6.5 via +commit 61d7e8274cd8 (xfs: drop EXPERIMENTAL tag for large extent +counts). + +Further, xfsprogs release v6.5.0 switched this feature on by default +in mkfs.xfs via commit e5b18d7d1d96 (mkfs: enable large extent counts +by default). + +Filesystems formatted with large extent count support, nrext64=1, are +thus currently not recognizable by GRUB, since this is an incompat +feature. Add the required support so that those filesystems and inodes +with large extent counters can be read by GRUB. + +Signed-off-by: Anthony Iliopoulos +Reviewed-by: Andrey Albershteyn +Reviewed-by: Daniel Kiper +Tested-by: Marta Lewandowska +Tested-by: Sebastian Andrzej Siewior +--- + grub-core/fs/xfs.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 18edfcff486c..bc2224dbb463 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -79,6 +79,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + /* Inode flags2 flags */ + #define XFS_DIFLAG2_BIGTIME_BIT 3 + #define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) ++#define XFS_DIFLAG2_NREXT64_BIT 4 ++#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT) + + /* incompat feature flags */ + #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +@@ -86,6 +88,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ + #define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ + #define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ ++#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ + + /* + * Directory entries with ftype are explicitly handled by GRUB code. +@@ -101,7 +104,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + XFS_SB_FEAT_INCOMPAT_SPINODES | \ + XFS_SB_FEAT_INCOMPAT_META_UUID | \ + XFS_SB_FEAT_INCOMPAT_BIGTIME | \ +- XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR) ++ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \ ++ XFS_SB_FEAT_INCOMPAT_NREXT64) + + struct grub_xfs_sblock + { +@@ -203,7 +207,8 @@ struct grub_xfs_inode + grub_uint16_t mode; + grub_uint8_t version; + grub_uint8_t format; +- grub_uint8_t unused2[26]; ++ grub_uint8_t unused2[18]; ++ grub_uint64_t nextents_big; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; +@@ -545,11 +550,26 @@ get_fsb (const void *keys, int idx) + return grub_be_to_cpu64 (grub_get_unaligned64 (p)); + } + ++static int ++grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode) ++{ ++ return inode->version >= 3 && ++ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64)); ++} ++ ++static grub_uint64_t ++grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode) ++{ ++ return (grub_xfs_inode_has_large_extent_counts (inode)) ? ++ grub_be_to_cpu64 (inode->nextents_big) : ++ grub_be_to_cpu32 (inode->nextents); ++} ++ + static grub_disk_addr_t + grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + { + struct grub_xfs_btree_node *leaf = 0; +- int ex, nrec; ++ grub_uint64_t ex, nrec; + struct grub_xfs_extent *exts; + grub_uint64_t ret = 0; + +@@ -574,7 +594,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + / (2 * sizeof (grub_uint64_t)); + do + { +- int i; ++ grub_uint64_t i; + + for (i = 0; i < nrec; i++) + { +@@ -621,7 +641,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) + grub_addr_t exts_end = 0; + grub_addr_t data_end = 0; + +- nrec = grub_be_to_cpu32 (node->inode.nextents); ++ nrec = grub_xfs_get_inode_nextents (&node->inode); + exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); + + if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) || diff --git a/grub.patches b/grub.patches index 7228ddef..0ce0db20 100644 --- a/grub.patches +++ b/grub.patches @@ -338,3 +338,9 @@ Patch0337: 0337-Fix-missing-include-in-ofdisk.c.patch Patch0338: 0338-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch Patch0339: 0339-grub-install-on-EFI-if-forced.patch Patch0340: 0340-Remove-Install-section-from-aux-systemd-units.patch +Patch0341: 0341-fs-Remove-trailing-whitespaces.patch +Patch0342: 0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch +Patch0343: 0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch +Patch0344: 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch +Patch0345: 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch +Patch0346: 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch diff --git a/grub2.spec b/grub2.spec index 4fba8400..47e8aa39 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 109%{?dist} +Release: 110%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Dec 1 2023 Nicolas Frayer - 2.06-110 +- fs/xfs: Add several fixes/improvements to xfs fs from upstream +- Resolves: #2247926 + * Wed Nov 15 2023 Nicolas Frayer - 2.06-109 - Linker: added --no-warn-rwx-segments as build will fail after ld.bfd default options have been changed. From 463f18634f1f3115f28a0f9fbb4a800f7b76e608 Mon Sep 17 00:00:00 2001 From: Leo Sandoval Date: Tue, 12 Dec 2023 18:26:32 -0600 Subject: [PATCH 17/27] chainloader: remove device path debug message Signed-off-by: Leo Sandoval --- ...der-remove-device-path-debug-message.patch | 28 +++++++++++++++++++ grub.patches | 1 + grub2.spec | 5 +++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 0347-chainloader-remove-device-path-debug-message.patch diff --git a/0347-chainloader-remove-device-path-debug-message.patch b/0347-chainloader-remove-device-path-debug-message.patch new file mode 100644 index 00000000..ef7720f8 --- /dev/null +++ b/0347-chainloader-remove-device-path-debug-message.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: raravind +Date: Tue, 9 May 2023 11:29:35 +0200 +Subject: [PATCH] chainloader: remove device path debug message + +Remove the debug message "/EndEntire" while using GRUB chainloader command. + +Signed-off-by: raravind +(cherry picked from commit f75f5386b7a6a7cb2e10d30f817a3564c0a28dd7) +--- + grub-core/loader/efi/chainloader.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index dd31ac9bb..b1c86dab2 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -210,7 +210,6 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) + /* Fill the file path for the directory. */ + d = (grub_efi_device_path_t *) ((char *) file_path + + ((char *) d - (char *) dp)); +- grub_efi_print_device_path (d); + if (copy_file_path ((grub_efi_file_path_device_path_t *) d, + dir_start, dir_end - dir_start) != GRUB_ERR_NONE) + { +-- +2.43.0 + diff --git a/grub.patches b/grub.patches index 0ce0db20..76772d43 100644 --- a/grub.patches +++ b/grub.patches @@ -344,3 +344,4 @@ Patch0343: 0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch Patch0344: 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch Patch0345: 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch Patch0346: 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch +Patch0347: 0347-chainloader-remove-device-path-debug-message.patch \ No newline at end of file diff --git a/grub2.spec b/grub2.spec index 47e8aa39..1fa83ee8 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 110%{?dist} +Release: 111%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Tue Dec 12 2023 leo sandoval - 2.06-111 +- chainloader: remove device path debug message + * Fri Dec 1 2023 Nicolas Frayer - 2.06-110 - fs/xfs: Add several fixes/improvements to xfs fs from upstream - Resolves: #2247926 From d32334821b462ec1731bdc2998e0ac0a39e8f10f Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Tue, 19 Dec 2023 17:32:37 +0100 Subject: [PATCH 18/27] normal: fix prefix when loading modules Resolves: #2209435 Resolves: #2173015 Signed-off-by: Nicolas Frayer --- ...ub_env_set-prefix-in-grub_try_normal.patch | 27 +++++++++++++++++++ grub.patches | 3 ++- grub2.spec | 7 ++++- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch diff --git a/0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch b/0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch new file mode 100644 index 00000000..900c59a0 --- /dev/null +++ b/0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nicolas Frayer +Date: Tue, 19 Dec 2023 16:52:05 +0100 +Subject: [PATCH] normal: Remove grub_env_set prefix in grub_try_normal_prefix + +Commit de735a453aa35 added a grub_env_set where the prefix contains +the arch name in the pathname. This create issues when trying to +load modules using this prefix as the pathname contains a "doubled" +arch name in it (ie .../powerpc-ieee1275/powerpc-ieee1275/). + +Signed-off-by: Nicolas Frayer +--- + grub-core/normal/main.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c +index d59145f861d5..bac7b8a0e1d8 100644 +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -372,7 +372,6 @@ grub_try_normal_prefix (const char *prefix) + file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG); + if (file) + { +- grub_env_set ("prefix", prefix); + grub_file_close (file); + err = GRUB_ERR_NONE; + } diff --git a/grub.patches b/grub.patches index 76772d43..7faf27d5 100644 --- a/grub.patches +++ b/grub.patches @@ -344,4 +344,5 @@ Patch0343: 0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch Patch0344: 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch Patch0345: 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch Patch0346: 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch -Patch0347: 0347-chainloader-remove-device-path-debug-message.patch \ No newline at end of file +Patch0347: 0347-chainloader-remove-device-path-debug-message.patch +Patch0348: 0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch diff --git a/grub2.spec b/grub2.spec index 1fa83ee8..f1d983ee 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 111%{?dist} +Release: 112%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Tue Dec 19 2023 Nicolas Frayer - 2.06-112 +- normal: fix prefix when loading modules +- Resolves: #2209435 +- Resolves: #2173015 + * Tue Dec 12 2023 leo sandoval - 2.06-111 - chainloader: remove device path debug message From b601fadc1325642ec0017c3dba5aabe37550bb9a Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Mon, 8 Jan 2024 16:19:01 +0100 Subject: [PATCH 19/27] xfs: Remove directory extent parsing patch Some bios systems with /boot partition created with xfsprog < 6.5.0 can't boot with one of the xfs upstream patches Resolves: #2254370 Signed-off-by: Nicolas Frayer --- ...-extent-counters-incompat-feature-su.patch | 0 ...xfs-Fix-XFS-directory-extent-parsing.patch | 168 ------------------ ...der-remove-device-path-debug-message.patch | 0 ...ub_env_set-prefix-in-grub_try_normal.patch | 0 grub.patches | 7 +- grub2.spec | 7 +- 6 files changed, 9 insertions(+), 173 deletions(-) rename 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch => 0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch (100%) delete mode 100644 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch rename 0347-chainloader-remove-device-path-debug-message.patch => 0346-chainloader-remove-device-path-debug-message.patch (100%) rename 0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch => 0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch (100%) diff --git a/0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch b/0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch similarity index 100% rename from 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch rename to 0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch diff --git a/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch b/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch deleted file mode 100644 index c0057310..00000000 --- a/0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jon DeVree -Date: Tue, 17 Oct 2023 23:03:47 -0400 -Subject: [PATCH] fs/xfs: Fix XFS directory extent parsing - -The XFS directory entry parsing code has never been completely correct -for extent based directories. The parser correctly handles the case -where the directory is contained in a single extent, but then mistakenly -assumes the data blocks for the multiple extent case are each identical -to the single extent case. The difference in the format of the data -blocks between the two cases is tiny enough that its gone unnoticed for -a very long time. - -A recent change introduced some additional bounds checking into the XFS -parser. Like GRUB's existing parser, it is correct for the single extent -case but incorrect for the multiple extent case. When parsing a directory -with multiple extents, this new bounds checking is sometimes (but not -always) tripped and triggers an "invalid XFS directory entry" error. This -probably would have continued to go unnoticed but the /boot/grub/ -directory is large enough that it often has multiple extents. - -The difference between the two cases is that when there are multiple -extents, the data blocks do not contain a trailer nor do they contain -any leaf information. That information is stored in a separate set of -extents dedicated to just the leaf information. These extents come after -the directory entry extents and are not included in the inode size. So -the existing parser already ignores the leaf extents. - -The only reason to read the trailer/leaf information at all is so that -the parser can avoid misinterpreting that data as directory entries. So -this updates the parser as follows: - -For the single extent case the parser doesn't change much: -1. Read the size of the leaf information from the trailer -2. Set the end pointer for the parser to the start of the leaf - information. (The previous bounds checking set the end pointer to the - start of the trailer, so this is actually a small improvement.) -3. Set the entries variable to the expected number of directory entries. - -For the multiple extent case: -1. Set the end pointer to the end of the block. -2. Do not set up the entries variable. Figuring out how many entries are - in each individual block is complex and does not seem worth it when - it appears to be safe to just iterate over the entire block. - -The bounds check itself was also dependent upon the faulty XFS parser -because it accidentally used "filename + length - 1". Presumably this -was able to pass the fuzzer because in the old parser there was always -8 bytes of slack space between the tail pointer and the actual end of -the block. Since this is no longer the case the bounds check needs to be -updated to "filename + length + 1" in order to prevent a regression in -the handling of corrupt fliesystems. - -Notes: -* When there is only one extent there will only ever be one block. If - more than one block is required then XFS will always switch to holding - leaf information in a separate extent. -* B-tree based directories seems to be parsed properly by the same code - that handles multiple extents. This is unlikely to ever occur within - /boot though because its only used when there are an extremely large - number of directory entries. - -Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem) -Fixes: b2499b29c (Adds support for the XFS filesystem.) -Fixes: https://savannah.gnu.org/bugs/?64376 - -Signed-off-by: Jon DeVree -Reviewed-by: Daniel Kiper -Tested-by: Sebastian Andrzej Siewior -Tested-by: Marta Lewandowska ---- - grub-core/fs/xfs.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- - 1 file changed, 38 insertions(+), 14 deletions(-) - -diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c -index ebf962793fa7..18edfcff486c 100644 ---- a/grub-core/fs/xfs.c -+++ b/grub-core/fs/xfs.c -@@ -223,6 +223,12 @@ struct grub_xfs_inode - /* Size of struct grub_xfs_inode v2, up to unused4 member included. */ - #define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) - -+struct grub_xfs_dir_leaf_entry -+{ -+ grub_uint32_t hashval; -+ grub_uint32_t address; -+} GRUB_PACKED; -+ - struct grub_xfs_dirblock_tail - { - grub_uint32_t leaf_count; -@@ -874,9 +880,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - { - struct grub_xfs_dir2_entry *direntry = - grub_xfs_first_de(dir->data, dirblock); -- int entries; -- struct grub_xfs_dirblock_tail *tail = -- grub_xfs_dir_tail(dir->data, dirblock); -+ int entries = -1; -+ char *end = dirblock + dirblk_size; - - numread = grub_xfs_read_file (dir, 0, 0, - blk << dirblk_log2, -@@ -887,14 +892,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - return 0; - } - -- entries = (grub_be_to_cpu32 (tail->leaf_count) -- - grub_be_to_cpu32 (tail->leaf_stale)); -+ /* -+ * Leaf and tail information are only in the data block if the number -+ * of extents is 1. -+ */ -+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) -+ { -+ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); - -- if (!entries) -- continue; -+ end = (char *) tail; -+ -+ /* Subtract the space used by leaf nodes. */ -+ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry); -+ -+ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale); -+ -+ if (!entries) -+ continue; -+ } - - /* Iterate over all entries within this block. */ -- while ((char *)direntry < (char *)tail) -+ while ((char *) direntry < (char *) end) - { - grub_uint8_t *freetag; - char *filename; -@@ -914,7 +932,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - } - - filename = (char *)(direntry + 1); -- if (filename + direntry->len - 1 > (char *) tail) -+ if (filename + direntry->len + 1 > (char *) end) - return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); - - /* The byte after the filename is for the filetype, padding, or -@@ -928,11 +946,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - return 1; - } - -- /* Check if last direntry in this block is -- reached. */ -- entries--; -- if (!entries) -- break; -+ /* -+ * The expected number of directory entries is only tracked for the -+ * single extent case. -+ */ -+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) -+ { -+ /* Check if last direntry in this block is reached. */ -+ entries--; -+ if (!entries) -+ break; -+ } - - /* Select the next directory entry. */ - direntry = grub_xfs_next_de(dir->data, direntry); diff --git a/0347-chainloader-remove-device-path-debug-message.patch b/0346-chainloader-remove-device-path-debug-message.patch similarity index 100% rename from 0347-chainloader-remove-device-path-debug-message.patch rename to 0346-chainloader-remove-device-path-debug-message.patch diff --git a/0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch b/0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch similarity index 100% rename from 0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch rename to 0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch diff --git a/grub.patches b/grub.patches index 7faf27d5..e791a0ba 100644 --- a/grub.patches +++ b/grub.patches @@ -342,7 +342,6 @@ Patch0341: 0341-fs-Remove-trailing-whitespaces.patch Patch0342: 0342-fs-xfs-Fix-memory-leaks-in-XFS-module.patch Patch0343: 0343-fs-xfs-Fix-issues-found-while-fuzzing-the-XFS-filesy.patch Patch0344: 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch -Patch0345: 0345-fs-xfs-Fix-XFS-directory-extent-parsing.patch -Patch0346: 0346-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch -Patch0347: 0347-chainloader-remove-device-path-debug-message.patch -Patch0348: 0348-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch +Patch0345: 0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch +Patch0346: 0346-chainloader-remove-device-path-debug-message.patch +Patch0347: 0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch diff --git a/grub2.spec b/grub2.spec index f1d983ee..485f87ad 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 112%{?dist} +Release: 113%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Mon Jan 8 2024 Nicolas Frayer - 2.06-113 +- xfs: some bios systems with /boot partition created with + xfsprog < 6.5.0 can't boot with one of the xfs upstream patches +- Resolves: #2254370 + * Tue Dec 19 2023 Nicolas Frayer - 2.06-112 - normal: fix prefix when loading modules - Resolves: #2209435 From ba9140291053e3d00f51f426315f0713d7cd5acc Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 11 Jan 2024 18:52:21 +0100 Subject: [PATCH 20/27] Drop grub2-tools obsoletes for grub2-tools-minimal When installing grub2-tools grub2-tools-minimal is pulled in which obsoletes grub2-tools causing grub2-tools to not get installed. Remove the obsoletes so that grub2-tools can be installed again. Signed-off-by: Daan De Meyer --- grub2.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/grub2.spec b/grub2.spec index 485f87ad..2ea8beaa 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 113%{?dist} +Release: 114%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -135,7 +135,6 @@ This subpackage provides tools for support of EFI platforms. Summary: Support tools for GRUB. Requires: gettext-runtime Requires: grub2-common = %{epoch}:%{version}-%{release} -Obsoletes: grub2-tools < %{evr} %description tools-minimal %{desc} @@ -555,6 +554,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Thu Jan 11 2024 Daan De Meyer - 2.06-114 +- Don't obsolete the tools package with minimal + * Mon Jan 8 2024 Nicolas Frayer - 2.06-113 - xfs: some bios systems with /boot partition created with xfsprog < 6.5.0 can't boot with one of the xfs upstream patches From 4afdc36e08add7f2928d58a925e4b7bbd079622b Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Wed, 10 Jan 2024 22:35:30 +0900 Subject: [PATCH 21/27] Switch memdisk compression to lzop xz decompression is very slow and slows down boot by around 5 seconds on aarch64/Apple M1 when using the default font. Switch to lzop, which takes less than one second to uncompress. This increases EFI core image size by around 11%. Signed-off-by: Hector Martin --- grub.macros | 6 +++--- grub2.spec | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/grub.macros b/grub.macros index 0198ffc3..241baf82 100644 --- a/grub.macros +++ b/grub.macros @@ -419,7 +419,7 @@ rm -f %{1}.conf \ %define efi_mkimage() \ mkdir -p memdisk/fonts \ cp %{4}/unicode.pf2 memdisk/fonts \ -mksquashfs memdisk memdisk.squashfs -comp xz \ +mksquashfs memdisk memdisk.squashfs -comp lzo \ %{4}./grub-mkimage -O %{1} -o %{2}.orig \\\ -d grub-core \\\ --sbat %{4}./sbat.csv \\\ @@ -448,14 +448,14 @@ mksquashfs memdisk memdisk.squashfs -comp xz \ %define ieee1275_mkimage() \ mkdir -p memdisk/fonts \ cp %{5}/unicode.pf2 memdisk/fonts \ -mksquashfs memdisk memdisk.squashfs -comp xz \ +mksquashfs memdisk memdisk.squashfs -comp lzo \ ./grub-mkimage -O %{1} -o %{2} -p '/grub2' -d grub-core ${GRUB_MODULES} \ %{nil} %else %define ieee1275_mkimage() \ mkdir -p memdisk/fonts \ cp %{5}/unicode.pf2 memdisk/fonts \ -mksquashfs memdisk memdisk.squashfs -comp xz \ +mksquashfs memdisk memdisk.squashfs -comp lzo \ APPENDED_SIG_SIZE=0 \ if [ -x /usr/bin/rpm-sign ]; then \ touch empty.unsigned \ diff --git a/grub2.spec b/grub2.spec index 2ea8beaa..e0eabe27 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 114%{?dist} +Release: 115%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -554,6 +554,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Sat Jan 13 2024 Hector Martin - 2.06-115 +- Switch memdisk compression to lzop + * Thu Jan 11 2024 Daan De Meyer - 2.06-114 - Don't obsolete the tools package with minimal From 111a2e2ad7dc9b8c0f0f5296f7969a886976d250 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Wed, 25 Oct 2023 16:57:09 +0200 Subject: [PATCH 22/27] grub-core/commands: add flag to only search root dev Resolves: #2223437 Resolves: #2224951 Resolves: #2258096 Resolves: CVE-2023-4001 Signed-off-by: Nicolas Frayer --- 0348-add-flag-to-only-search-root-dev.patch | 160 ++++++++++++++++++++ grub.patches | 1 + grub2.spec | 11 +- 3 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 0348-add-flag-to-only-search-root-dev.patch diff --git a/0348-add-flag-to-only-search-root-dev.patch b/0348-add-flag-to-only-search-root-dev.patch new file mode 100644 index 00000000..8ae8875a --- /dev/null +++ b/0348-add-flag-to-only-search-root-dev.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Marta Lewandowska +Date: Mon, 9 Oct 2023 08:53:18 +0200 +Subject: [PATCH] add flag to only search root dev + +fixes bz#2223437 + +Signed-off-by: Marta Lewandowska +--- + grub-core/commands/search.c | 36 ++++++++++++++++++++++++++++++++++++ + grub-core/commands/search_wrap.c | 5 +++++ + grub-core/kern/misc.c | 30 ++++++++++++++++++++++++++++++ + include/grub/misc.h | 1 + + include/grub/search.h | 3 ++- + 5 files changed, 74 insertions(+), 1 deletion(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index 57d26ced8a8e..819231751c38 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -85,6 +85,42 @@ iterate_device (const char *name, void *data) + grub_device_close (dev); + } + ++ /* Skip it if it's not the root device when requested. */ ++ if (ctx->flags & SEARCH_FLAGS_ROOTDEV_ONLY) ++ { ++ const char *root_dev; ++ root_dev = grub_env_get ("root"); ++ if (root_dev != NULL && *root_dev != '\0') ++ { ++ char *root_disk = grub_malloc (grub_strlen(root_dev) + 1); ++ char *name_disk = grub_malloc (grub_strlen(name) + 1); ++ char *rem_1 = grub_malloc(grub_strlen(root_dev) + 1); ++ char *rem_2 = grub_malloc(grub_strlen(name) + 1); ++ ++ if (root_disk != NULL && name_disk != NULL && ++ rem_1 != NULL && rem_2 != NULL) ++ { ++ /* get just the disk name; partitions will be different. */ ++ grub_str_sep (root_dev, root_disk, ',', rem_1); ++ grub_str_sep (name, name_disk, ',', rem_2); ++ if (root_disk != NULL && *root_disk != '\0' && ++ name_disk != NULL && *name_disk != '\0') ++ if (grub_strcmp(root_disk, name_disk) != 0) ++ { ++ grub_free (root_disk); ++ grub_free (name_disk); ++ grub_free (rem_1); ++ grub_free (rem_2); ++ return 0; ++ } ++ } ++ grub_free (root_disk); ++ grub_free (name_disk); ++ grub_free (rem_1); ++ grub_free (rem_2); ++ } ++ } ++ + #ifdef DO_SEARCH_FS_UUID + #define compare_fn grub_strcasecmp + #else +diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c +index 0b62acf85359..06b5f51eefb5 100644 +--- a/grub-core/commands/search_wrap.c ++++ b/grub-core/commands/search_wrap.c +@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] = + ARG_TYPE_STRING}, + {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, + {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, ++ {"root-dev-only", 'r', 0, N_("Only probe root device."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, +@@ -75,6 +76,7 @@ enum options + SEARCH_SET, + SEARCH_NO_FLOPPY, + SEARCH_EFIDISK_ONLY, ++ SEARCH_ROOTDEV_ONLY, + SEARCH_HINT, + SEARCH_HINT_IEEE1275, + SEARCH_HINT_BIOS, +@@ -189,6 +191,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) + if (state[SEARCH_EFIDISK_ONLY].set) + flags |= SEARCH_FLAGS_EFIDISK_ONLY; + ++ if (state[SEARCH_ROOTDEV_ONLY].set) ++ flags |= SEARCH_FLAGS_ROOTDEV_ONLY; ++ + if (state[SEARCH_LABEL].set) + grub_search_label (id, var, flags, hints, nhints); + else if (state[SEARCH_FS_UUID].set) +diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c +index cb454614022f..c0ac7fee6cc2 100644 +--- a/grub-core/kern/misc.c ++++ b/grub-core/kern/misc.c +@@ -619,6 +619,36 @@ grub_reverse (char *str) + } + } + ++/* Separate string into two parts, broken up by delimiter delim. */ ++void ++grub_str_sep (const char *s, char *p, char delim, char *r) ++{ ++ char* t = grub_strndup(s, grub_strlen(s)); ++ ++ if (t != NULL && *t != '\0') ++ { ++ char* tmp = t; ++ ++ while (((*p = *t) != '\0') && ((*p = *t) != delim)) ++ { ++ p++; ++ t++; ++ } ++ *p = '\0'; ++ ++ if (*t != '\0') ++ { ++ t++; ++ while ((*r++ = *t++) != '\0') ++ ; ++ *r = '\0'; ++ } ++ grub_free (tmp); ++ } ++ else ++ grub_free (t); ++} ++ + /* Divide N by D, return the quotient, and store the remainder in *R. */ + grub_uint64_t + grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) +diff --git a/include/grub/misc.h b/include/grub/misc.h +index faae0ae8606c..981526644d29 100644 +--- a/include/grub/misc.h ++++ b/include/grub/misc.h +@@ -314,6 +314,7 @@ void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); + grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) WARN_UNUSED_RESULT; + int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); + int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2))); ++void EXPORT_FUNC(grub_str_sep) (const char *s, char *p, char delim, char *r); + + /* Replace all `ch' characters of `input' with `with' and copy the + result into `output'; return EOS address of `output'. */ +diff --git a/include/grub/search.h b/include/grub/search.h +index 4190aeb2cbf5..321d1400e451 100644 +--- a/include/grub/search.h ++++ b/include/grub/search.h +@@ -22,7 +22,8 @@ + enum search_flags + { + SEARCH_FLAGS_NO_FLOPPY = 1, +- SEARCH_FLAGS_EFIDISK_ONLY = 2 ++ SEARCH_FLAGS_EFIDISK_ONLY = 2, ++ SEARCH_FLAGS_ROOTDEV_ONLY = 4 + }; + + void grub_search_fs_file (const char *key, const char *var, diff --git a/grub.patches b/grub.patches index e791a0ba..caf506f6 100644 --- a/grub.patches +++ b/grub.patches @@ -345,3 +345,4 @@ Patch0344: 0344-fs-xfs-Incorrect-short-form-directory-data-boundary-.patch Patch0345: 0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch Patch0346: 0346-chainloader-remove-device-path-debug-message.patch Patch0347: 0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch +Patch0348: 0348-add-flag-to-only-search-root-dev.patch diff --git a/grub2.spec b/grub2.spec index e0eabe27..04c2708c 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 115%{?dist} +Release: 116%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -368,7 +368,7 @@ BOOT_UUID=$(grub2-probe --target=fs_uuid ${GRUB_HOME}) GRUB_DIR=$(grub2-mkrelpath ${GRUB_HOME}) cat << EOF > ${EFI_HOME}/grub.cfg.stb -search --no-floppy --fs-uuid --set=dev ${BOOT_UUID} +search --no-floppy --root-dev-only --fs-uuid --set=dev ${BOOT_UUID} set prefix=(\$dev)${GRUB_DIR} export \$prefix configfile \$prefix/grub.cfg @@ -554,6 +554,13 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Mon Jan 15 2024 Nicolas Frayer - 2.06-116 +- grub-core/commands: add flag to only search root dev +- Resolves: #2223437 +- Resolves: #2224951 +- Resolves: #2258096 +- Resolves: CVE-2023-4001 + * Sat Jan 13 2024 Hector Martin - 2.06-115 - Switch memdisk compression to lzop From 700a33cd9bd965aede4564f4d1b6c9775441ce7e Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Wed, 7 Feb 2024 11:35:31 +0100 Subject: [PATCH 23/27] grub-set-bootflag: Fix for CVE-2024-1048 (CVE-2024-1048) Resolves: #2256678 Signed-off-by: Nicolas Frayer --- ...g-Conservative-partial-fix-for-CVE-2.patch | 146 ++++++++++++++ ...g-More-complete-fix-for-CVE-2024-104.patch | 187 ++++++++++++++++++ ...g-Exit-calmly-when-not-running-as-ro.patch | 36 ++++ grub.patches | 3 + grub2.spec | 7 +- 5 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch create mode 100644 0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch create mode 100644 0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch diff --git a/0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch b/0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch new file mode 100644 index 00000000..d20f909b --- /dev/null +++ b/0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 21:39:41 +0100 +Subject: [PATCH] grub-set-bootflag: Conservative partial fix for CVE-2024-1048 + +Following up on CVE-2019-14865 and taking a fresh look at +grub2-set-bootflag now (through my work at CIQ on Rocky Linux), I saw some +other ways in which users could still abuse this little program: + +1. After CVE-2019-14865 fix, grub2-set-bootflag no longer rewrites the +grubenv file in-place, but writes into a temporary file and renames it +over the original, checking for error returns from each call first. +This prevents the original file truncation vulnerability, but it can +leave the temporary file around if the program is killed before it can +rename or remove the file. There are still many ways to get the program +killed, such as through RLIMIT_FSIZE triggering SIGXFSZ (tested, +reliable) or by careful timing (tricky) of signals sent by process group +leader, pty, pre-scheduled timers, SIGXCPU (probably not an exhaustive +list). Invoking the program multiple times fills up /boot (or if /boot +is not separate, then it can fill up the root filesystem). Since the +files are tiny, the filesystem is likely to run out of free inodes +before it'd run out of blocks, but the effect is similar - can't create +new files after this point (but still can add data to existing files, +such as logs). + +2. After CVE-2019-14865 fix, grub2-set-bootflag naively tries to protect +itself from signals by becoming full root. (This does protect it from +signals sent by the user directly to the PID, but e.g. "kill -9 -1" by +the user still works.) A side effect of such "protection" is that it's +possible to invoke more concurrent instances of grub2-set-bootflag than +the user's RLIMIT_NPROC would normally permit (as specified e.g. in +/etc/security/limits.conf, or say in Apache httpd's RLimitNPROC if +grub2-set-bootflag would be abused by a website script), thereby +exhausting system resources (e.g., bypassing RAM usage limit if +RLIMIT_AS was also set). + +3. umask is inherited. Again, due to how the CVE-2019-14865 fix creates +a new file, and due to how mkstemp() works, this affects grubenv's new +file permissions. Luckily, mkstemp() forces them to be no more relaxed +than 0600, but the user ends up being able to set them e.g. to 0. +Luckily, at least in my testing GRUB still works fine even when the file +has such (lack of) permissions. + +This commit deals with the abuses above as follows: + +1. RLIMIT_FSIZE is pre-checked, so this specific way to get the process +killed should no longer work. However, this isn't a complete fix +because there are other ways to get the process killed after it has +created the temporary file. + +The commit also fixes bug 1975892 ("RFE: grub2-set-bootflag should not +write the grubenv when the flag being written is already set") and +similar for "menu_show_once", which further reduces the abuse potential. + +2. RLIMIT_NPROC bypass should be avoided by not becoming full root (aka +dropping the partial "kill protection"). + +3. A safe umask is set. + +This is a partial fix (temporary files can still accumulate, but this is +harder to trigger). + +While at it, this commit also fixes potential 1- or 2-byte over-read of +env[] if its content is malformed - this was not a security issue since the +grubenv file is trusted input, and the fix is just for robustness. + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 3b4c25ca2ac6..5bbbef804391 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -33,6 +33,8 @@ + #include + #include + #include ++#include ++#include + + #include "progname.h" + +@@ -57,12 +59,17 @@ static void usage(FILE *out) + int main(int argc, char *argv[]) + { + /* NOTE buf must be at least the longest bootflag length + 4 bytes */ +- char env[GRUBENV_SIZE + 1], buf[64], *s; ++ char env[GRUBENV_SIZE + 1 + 2], buf[64], *s; + /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ + char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; + const char *bootflag; + int i, fd, len, ret; + FILE *f; ++ struct rlimit rlim; ++ ++ if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) ++ return 1; ++ umask(077); + + if (argc != 2) + { +@@ -94,20 +101,11 @@ int main(int argc, char *argv[]) + len = strlen (bootflag); + + /* +- * Really become root. setuid avoids an user killing us, possibly leaking +- * the tmpfile. setgid avoids the new grubenv's gid being that of the user. ++ * setegid avoids the new grubenv's gid being that of the user. + */ +- ret = setuid(0); +- if (ret) ++ if (setegid(0)) + { +- perror ("Error setuid(0) failed"); +- return 1; +- } +- +- ret = setgid(0); +- if (ret) +- { +- perror ("Error setgid(0) failed"); ++ perror ("Error setegid(0) failed"); + return 1; + } + +@@ -136,6 +134,9 @@ int main(int argc, char *argv[]) + + /* 0 terminate env */ + env[GRUBENV_SIZE] = 0; ++ /* not a valid flag value */ ++ env[GRUBENV_SIZE + 1] = 0; ++ env[GRUBENV_SIZE + 2] = 0; + + if (strncmp (env, GRUB_ENVBLK_SIGNATURE, strlen (GRUB_ENVBLK_SIGNATURE))) + { +@@ -171,6 +172,8 @@ int main(int argc, char *argv[]) + + /* The grubenv is not 0 terminated, so memcpy the name + '=' , '1', '\n' */ + snprintf(buf, sizeof(buf), "%s=1\n", bootflag); ++ if (!memcmp(s, buf, len + 3)) ++ return 0; /* nothing to do */ + memcpy(s, buf, len + 3); + + diff --git a/0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch b/0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch new file mode 100644 index 00000000..b47b3110 --- /dev/null +++ b/0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch @@ -0,0 +1,187 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 21:56:21 +0100 +Subject: [PATCH] grub-set-bootflag: More complete fix for CVE-2024-1048 + +Switch to per-user fixed temporary filenames along with a weird locking +mechanism, which is explained in source code comments. This is a more +complete fix than the previous commit (temporary files can't accumulate). +Unfortunately, it introduces new risks (by working on a temporary file +shared between the user's invocations), which are _hopefully_ avoided by +the patch's elaborate logic. I actually got it wrong at first, which +suggests that this logic is hard to reason about, and more errors or +omissions are possible. It also relies on the kernel's primitives' exact +semantics to a greater extent (nothing out of the ordinary, though). + +Remaining issues that I think cannot reasonably be fixed without a +redesign (e.g., having per-flag files with nothing else in them) and +without introducing new issues: + +A. A user can still revert a concurrent user's attempt of setting the +other flag - or of making other changes to grubenv by means other than +this program. + +B. One leftover temporary file per user is still possible. + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 95 ++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 79 insertions(+), 16 deletions(-) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 5bbbef804391..514c4f9091ac 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -60,15 +61,12 @@ int main(int argc, char *argv[]) + { + /* NOTE buf must be at least the longest bootflag length + 4 bytes */ + char env[GRUBENV_SIZE + 1 + 2], buf[64], *s; +- /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */ +- char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1]; ++ /* +1 for 0 termination, +11 for ".%u" in tmp filename */ ++ char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 11 + 1]; + const char *bootflag; + int i, fd, len, ret; + FILE *f; +- struct rlimit rlim; + +- if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) +- return 1; + umask(077); + + if (argc != 2) +@@ -105,7 +103,7 @@ int main(int argc, char *argv[]) + */ + if (setegid(0)) + { +- perror ("Error setegid(0) failed"); ++ perror ("setegid(0) failed"); + return 1; + } + +@@ -176,19 +174,82 @@ int main(int argc, char *argv[]) + return 0; /* nothing to do */ + memcpy(s, buf, len + 3); + ++ struct rlimit rlim; ++ if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE) ++ { ++ fprintf (stderr, "Resource limits undetermined or too low\n"); ++ return 1; ++ } ++ ++ /* ++ * Here we work under the premise that we shouldn't write into the target ++ * file directly because we might not be able to have all of our changes ++ * written completely and atomically. That was CVE-2019-14865, known to ++ * have been triggerable via RLIMIT_FSIZE. While we've dealt with that ++ * specific attack via the check above, there may be other possibilities. ++ */ + + /* + * Create a tempfile for writing the new env. Use the canonicalized filename + * for the template so that the tmpfile is in the same dir / on same fs. ++ * ++ * We now use per-user fixed temporary filenames, so that a user cannot cause ++ * multiple files to accumulate. ++ * ++ * We don't use O_EXCL so that a stale temporary file doesn't prevent further ++ * usage of the program by the user. + */ +- snprintf(tmp_filename, sizeof(tmp_filename), "%sXXXXXX", env_filename); +- fd = mkstemp(tmp_filename); ++ snprintf(tmp_filename, sizeof(tmp_filename), "%s.%u", env_filename, getuid()); ++ fd = open(tmp_filename, O_CREAT | O_WRONLY, 0600); + if (fd == -1) + { + perror ("Creating tmpfile failed"); + return 1; + } + ++ /* ++ * The lock prevents the same user from reaching further steps ending in ++ * rename() concurrently, in which case the temporary file only partially ++ * written by one invocation could be renamed to the target file by another. ++ * ++ * The lock also guards the slow fsync() from concurrent calls. After the ++ * first time that and the rename() complete, further invocations for the ++ * same flag become no-ops. ++ * ++ * We lock the temporary file rather than the target file because locking the ++ * latter would allow any user having SIGSTOP'ed their process to make all ++ * other users' invocations fail (or lock up if we'd use blocking mode). ++ * ++ * We use non-blocking mode (LOCK_NB) because the lock having been taken by ++ * another process implies that the other process would normally have already ++ * renamed the file to target by the time it releases the lock (and we could ++ * acquire it), so we'd be working directly on the target if we proceeded, ++ * which is undesirable, and we'd kind of fail on the already-done rename. ++ */ ++ if (flock(fd, LOCK_EX | LOCK_NB)) ++ { ++ perror ("Locking tmpfile failed"); ++ return 1; ++ } ++ ++ /* ++ * Deal with the potential that another invocation proceeded all the way to ++ * rename() and process exit while we were between open() and flock(). ++ */ ++ { ++ struct stat st1, st2; ++ if (fstat(fd, &st1) || stat(tmp_filename, &st2)) ++ { ++ perror ("stat of tmpfile failed"); ++ return 1; ++ } ++ if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) ++ { ++ fprintf (stderr, "Another invocation won race\n"); ++ return 1; ++ } ++ } ++ + f = fdopen (fd, "w"); + if (!f) + { +@@ -213,6 +274,14 @@ int main(int argc, char *argv[]) + return 1; + } + ++ ret = ftruncate (fileno (f), GRUBENV_SIZE); ++ if (ret) ++ { ++ perror ("Error truncating tmpfile"); ++ unlink(tmp_filename); ++ return 1; ++ } ++ + ret = fsync (fileno (f)); + if (ret) + { +@@ -221,15 +290,9 @@ int main(int argc, char *argv[]) + return 1; + } + +- ret = fclose (f); +- if (ret) +- { +- perror ("Error closing tmpfile"); +- unlink(tmp_filename); +- return 1; +- } +- + /* ++ * We must not close the file before rename() as that would remove the lock. ++ * + * And finally rename the tmpfile with the new env over the old env, the + * linux kernel guarantees that this is atomic (from a syscall pov). + */ diff --git a/0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch b/0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch new file mode 100644 index 00000000..dba46d4a --- /dev/null +++ b/0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Solar Designer +Date: Tue, 6 Feb 2024 22:05:45 +0100 +Subject: [PATCH] grub-set-bootflag: Exit calmly when not running as root + +Exit calmly when not installed SUID root and invoked by non-root. This +allows installing user/grub-boot-success.service unconditionally while +supporting non-SUID installation of the program for some limited usage. + +Signed-off-by: Solar Designer +--- + util/grub-set-bootflag.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c +index 514c4f9091ac..31a868aeca8a 100644 +--- a/util/grub-set-bootflag.c ++++ b/util/grub-set-bootflag.c +@@ -98,6 +98,17 @@ int main(int argc, char *argv[]) + bootflag = bootflags[i]; + len = strlen (bootflag); + ++ /* ++ * Exit calmly when not installed SUID root and invoked by non-root. This ++ * allows installing user/grub-boot-success.service unconditionally while ++ * supporting non-SUID installation of the program for some limited usage. ++ */ ++ if (geteuid()) ++ { ++ printf ("grub-set-bootflag not running as root, no action taken\n"); ++ return 0; ++ } ++ + /* + * setegid avoids the new grubenv's gid being that of the user. + */ diff --git a/grub.patches b/grub.patches index caf506f6..156df9af 100644 --- a/grub.patches +++ b/grub.patches @@ -346,3 +346,6 @@ Patch0345: 0345-fs-xfs-Add-large-extent-counters-incompat-feature-su.patch Patch0346: 0346-chainloader-remove-device-path-debug-message.patch Patch0347: 0347-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch Patch0348: 0348-add-flag-to-only-search-root-dev.patch +Patch0349: 0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch +Patch0350: 0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch +Patch0351: 0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch diff --git a/grub2.spec b/grub2.spec index 04c2708c..2d8c4560 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 116%{?dist} +Release: 117%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -554,6 +554,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Feb 7 2024 Nicolas Frayer - 2.06-117 +- grub-set-bootflag: Fix for CVE-2024-1048 +- (CVE-2024-1048) +- Resolves: #2256678 + * Mon Jan 15 2024 Nicolas Frayer - 2.06-116 - grub-core/commands: add flag to only search root dev - Resolves: #2223437 From de8e46a702551acfe80c05b81afbdaaeff366fbf Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Mon, 12 Feb 2024 22:23:12 +0100 Subject: [PATCH 24/27] fs/xfs: Re-apply the XFS directory extent parsing patch Resolves: #2259266 Signed-off-by: Nicolas Frayer --- ...xfs-Fix-XFS-directory-extent-parsing.patch | 168 ++++++++++++++++++ grub.patches | 1 + grub2.spec | 6 +- 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch diff --git a/0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch b/0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch new file mode 100644 index 00000000..c0057310 --- /dev/null +++ b/0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch @@ -0,0 +1,168 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jon DeVree +Date: Tue, 17 Oct 2023 23:03:47 -0400 +Subject: [PATCH] fs/xfs: Fix XFS directory extent parsing + +The XFS directory entry parsing code has never been completely correct +for extent based directories. The parser correctly handles the case +where the directory is contained in a single extent, but then mistakenly +assumes the data blocks for the multiple extent case are each identical +to the single extent case. The difference in the format of the data +blocks between the two cases is tiny enough that its gone unnoticed for +a very long time. + +A recent change introduced some additional bounds checking into the XFS +parser. Like GRUB's existing parser, it is correct for the single extent +case but incorrect for the multiple extent case. When parsing a directory +with multiple extents, this new bounds checking is sometimes (but not +always) tripped and triggers an "invalid XFS directory entry" error. This +probably would have continued to go unnoticed but the /boot/grub/ +directory is large enough that it often has multiple extents. + +The difference between the two cases is that when there are multiple +extents, the data blocks do not contain a trailer nor do they contain +any leaf information. That information is stored in a separate set of +extents dedicated to just the leaf information. These extents come after +the directory entry extents and are not included in the inode size. So +the existing parser already ignores the leaf extents. + +The only reason to read the trailer/leaf information at all is so that +the parser can avoid misinterpreting that data as directory entries. So +this updates the parser as follows: + +For the single extent case the parser doesn't change much: +1. Read the size of the leaf information from the trailer +2. Set the end pointer for the parser to the start of the leaf + information. (The previous bounds checking set the end pointer to the + start of the trailer, so this is actually a small improvement.) +3. Set the entries variable to the expected number of directory entries. + +For the multiple extent case: +1. Set the end pointer to the end of the block. +2. Do not set up the entries variable. Figuring out how many entries are + in each individual block is complex and does not seem worth it when + it appears to be safe to just iterate over the entire block. + +The bounds check itself was also dependent upon the faulty XFS parser +because it accidentally used "filename + length - 1". Presumably this +was able to pass the fuzzer because in the old parser there was always +8 bytes of slack space between the tail pointer and the actual end of +the block. Since this is no longer the case the bounds check needs to be +updated to "filename + length + 1" in order to prevent a regression in +the handling of corrupt fliesystems. + +Notes: +* When there is only one extent there will only ever be one block. If + more than one block is required then XFS will always switch to holding + leaf information in a separate extent. +* B-tree based directories seems to be parsed properly by the same code + that handles multiple extents. This is unlikely to ever occur within + /boot though because its only used when there are an extremely large + number of directory entries. + +Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem) +Fixes: b2499b29c (Adds support for the XFS filesystem.) +Fixes: https://savannah.gnu.org/bugs/?64376 + +Signed-off-by: Jon DeVree +Reviewed-by: Daniel Kiper +Tested-by: Sebastian Andrzej Siewior +Tested-by: Marta Lewandowska +--- + grub-core/fs/xfs.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 38 insertions(+), 14 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index ebf962793fa7..18edfcff486c 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -223,6 +223,12 @@ struct grub_xfs_inode + /* Size of struct grub_xfs_inode v2, up to unused4 member included. */ + #define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + ++struct grub_xfs_dir_leaf_entry ++{ ++ grub_uint32_t hashval; ++ grub_uint32_t address; ++} GRUB_PACKED; ++ + struct grub_xfs_dirblock_tail + { + grub_uint32_t leaf_count; +@@ -874,9 +880,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + { + struct grub_xfs_dir2_entry *direntry = + grub_xfs_first_de(dir->data, dirblock); +- int entries; +- struct grub_xfs_dirblock_tail *tail = +- grub_xfs_dir_tail(dir->data, dirblock); ++ int entries = -1; ++ char *end = dirblock + dirblk_size; + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -887,14 +892,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 0; + } + +- entries = (grub_be_to_cpu32 (tail->leaf_count) +- - grub_be_to_cpu32 (tail->leaf_stale)); ++ /* ++ * Leaf and tail information are only in the data block if the number ++ * of extents is 1. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); + +- if (!entries) +- continue; ++ end = (char *) tail; ++ ++ /* Subtract the space used by leaf nodes. */ ++ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry); ++ ++ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale); ++ ++ if (!entries) ++ continue; ++ } + + /* Iterate over all entries within this block. */ +- while ((char *)direntry < (char *)tail) ++ while ((char *) direntry < (char *) end) + { + grub_uint8_t *freetag; + char *filename; +@@ -914,7 +932,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + } + + filename = (char *)(direntry + 1); +- if (filename + direntry->len - 1 > (char *) tail) ++ if (filename + direntry->len + 1 > (char *) end) + return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); + + /* The byte after the filename is for the filetype, padding, or +@@ -928,11 +946,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 1; + } + +- /* Check if last direntry in this block is +- reached. */ +- entries--; +- if (!entries) +- break; ++ /* ++ * The expected number of directory entries is only tracked for the ++ * single extent case. ++ */ ++ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1)) ++ { ++ /* Check if last direntry in this block is reached. */ ++ entries--; ++ if (!entries) ++ break; ++ } + + /* Select the next directory entry. */ + direntry = grub_xfs_next_de(dir->data, direntry); diff --git a/grub.patches b/grub.patches index 156df9af..e19dc868 100644 --- a/grub.patches +++ b/grub.patches @@ -349,3 +349,4 @@ Patch0348: 0348-add-flag-to-only-search-root-dev.patch Patch0349: 0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch Patch0350: 0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch Patch0351: 0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch +Patch0352: 0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch diff --git a/grub2.spec b/grub2.spec index 2d8c4560..4e767f5f 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 117%{?dist} +Release: 118%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -554,6 +554,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Feb 7 2024 Nicolas Frayer - 2.06-118 +- fs/xfs: Re-applied the XFS directory extent parsing patch +- Resolves: #2259266 + * Wed Feb 7 2024 Nicolas Frayer - 2.06-117 - grub-set-bootflag: Fix for CVE-2024-1048 - (CVE-2024-1048) From 4b81c6f969a8a34704bf6ed1e345fafddb0841f1 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Mon, 11 Mar 2024 14:53:44 +0100 Subject: [PATCH 25/27] GRUB2 NTFS driver vulnerabilities (CVE-2023-4692) (CVE-2023-4693) Resolves: #2236613 Resolves: #2241978 Resolves: #2241976 Resolves: #2238343 Signed-off-by: Nicolas Frayer --- ...OB-write-when-parsing-the-ATTRIBUTE_.patch | 90 ++++++++++ ...OB-read-when-reading-data-from-the-r.patch | 55 ++++++ ...OB-read-when-parsing-directory-entri.patch | 70 ++++++++ ...OB-read-when-parsing-bitmaps-for-ind.patch | 48 ++++++ ...OOB-read-when-parsing-a-volume-label.patch | 58 +++++++ 0358-fs-ntfs-Make-code-more-readable.patch | 156 ++++++++++++++++++ grub.patches | 6 + grub2.spec | 11 +- 8 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 0353-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch create mode 100644 0354-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch create mode 100644 0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch create mode 100644 0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch create mode 100644 0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch create mode 100644 0358-fs-ntfs-Make-code-more-readable.patch diff --git a/0353-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch b/0353-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch new file mode 100644 index 00000000..8c2905a6 --- /dev/null +++ b/0353-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:23 +0200 +Subject: [PATCH] fs/ntfs: Fix an OOB write when parsing the $ATTRIBUTE_LIST + attribute for the $MFT file + +When parsing an extremely fragmented $MFT file, i.e., the file described +using the $ATTRIBUTE_LIST attribute, current NTFS code will reuse a buffer +containing bytes read from the underlying drive to store sector numbers, +which are consumed later to read data from these sectors into another buffer. + +These sectors numbers, two 32-bit integers, are always stored at predefined +offsets, 0x10 and 0x14, relative to first byte of the selected entry within +the $ATTRIBUTE_LIST attribute. Usually, this won't cause any problem. + +However, when parsing a specially-crafted file system image, this may cause +the NTFS code to write these integers beyond the buffer boundary, likely +causing the GRUB memory allocator to misbehave or fail. These integers contain +values which are controlled by on-disk structures of the NTFS file system. + +Such modification and resulting misbehavior may touch a memory range not +assigned to the GRUB and owned by firmware or another EFI application/driver. + +This fix introduces checks to ensure that these sector numbers are never +written beyond the boundary. + +Fixes: CVE-2023-4692 + +Reported-by: Maxim Suhanov +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 3511e4e2cb6f..4681c7ac32a8 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -184,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + } + if (at->attr_end) + { +- grub_uint8_t *pa; ++ grub_uint8_t *pa, *pa_end; + + at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); + if (at->emft_buf == NULL) +@@ -209,11 +209,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + } + at->attr_nxt = at->edat_buf; + at->attr_end = at->edat_buf + u32at (pa, 0x30); ++ pa_end = at->edat_buf + n; + } + else + { + at->attr_nxt = at->attr_end + u16at (pa, 0x14); + at->attr_end = at->attr_end + u32at (pa, 4); ++ pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); + } + at->flags |= GRUB_NTFS_AF_ALST; + while (at->attr_nxt < at->attr_end) +@@ -230,6 +232,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + at->flags |= GRUB_NTFS_AF_GPOS; + at->attr_cur = at->attr_nxt; + pa = at->attr_cur; ++ ++ if ((pa >= pa_end) || (pa_end - pa < 0x18)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list"); ++ return NULL; ++ } ++ + grub_set_unaligned32 ((char *) pa + 0x10, + grub_cpu_to_le32 (at->mft->data->mft_start)); + grub_set_unaligned32 ((char *) pa + 0x14, +@@ -240,6 +249,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + { + if (*pa != attr) + break; ++ ++ if ((pa >= pa_end) || (pa_end - pa < 0x18)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list"); ++ return NULL; ++ } ++ + if (read_attr + (at, pa + 0x10, + u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), diff --git a/0354-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch b/0354-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch new file mode 100644 index 00000000..4b506f4f --- /dev/null +++ b/0354-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:24 +0200 +Subject: [PATCH] fs/ntfs: Fix an OOB read when reading data from the resident + $DATA attribute + +When reading a file containing resident data, i.e., the file data is stored in +the $DATA attribute within the NTFS file record, not in external clusters, +there are no checks that this resident data actually fits the corresponding +file record segment. + +When parsing a specially-crafted file system image, the current NTFS code will +read the file data from an arbitrary, attacker-chosen memory offset and of +arbitrary, attacker-chosen length. + +This allows an attacker to display arbitrary chunks of memory, which could +contain sensitive information like password hashes or even plain-text, +obfuscated passwords from BS EFI variables. + +This fix implements a check to ensure that resident data is read from the +corresponding file record segment only. + +Fixes: CVE-2023-4693 + +Reported-by: Maxim Suhanov +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 4681c7ac32a8..1949d48a494f 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -401,7 +401,18 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, + { + if (ofs + len > u32at (pa, 0x10)) + return grub_error (GRUB_ERR_BAD_FS, "read out of range"); +- grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len); ++ ++ if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large"); ++ ++ if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); ++ ++ if (u16at (pa, 0x14) + u32at (pa, 0x10) > ++ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa) ++ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); ++ ++ grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len); + return 0; + } + diff --git a/0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch b/0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch new file mode 100644 index 00000000..3b02cd5a --- /dev/null +++ b/0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:25 +0200 +Subject: [PATCH] fs/ntfs: Fix an OOB read when parsing directory entries from + resident and non-resident index attributes + +This fix introduces checks to ensure that index entries are never read +beyond the corresponding directory index. + +The lack of this check is a minor issue, likely not exploitable in any way. + +Reported-by: Maxim Suhanov +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 1949d48a494f..72302033281a 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -599,7 +599,7 @@ get_utf8 (grub_uint8_t *in, grub_size_t len) + } + + static int +-list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, ++list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) + { + grub_uint8_t *np; +@@ -610,6 +610,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, + grub_uint8_t namespace; + char *ustr; + ++ if ((pos >= end_pos) || (end_pos - pos < 0x52)) ++ break; ++ + if (pos[0xC] & 2) /* end signature */ + break; + +@@ -617,6 +620,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, + ns = *(np++); + namespace = *(np++); + ++ if (2 * ns > end_pos - pos - 0x52) ++ break; ++ + /* + * Ignore files in DOS namespace, as they will reappear as Win32 + * names. +@@ -802,7 +808,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + } + + cur_pos += 0x10; /* Skip index root */ +- ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data); ++ ret = list_file (mft, cur_pos + u16at (cur_pos, 0), ++ at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), ++ hook, hook_data); + if (ret) + goto done; + +@@ -889,6 +897,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + (const grub_uint8_t *) "INDX"))) + goto done; + ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], ++ indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), + hook, hook_data); + if (ret) + goto done; diff --git a/0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch b/0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch new file mode 100644 index 00000000..6e332b03 --- /dev/null +++ b/0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:26 +0200 +Subject: [PATCH] fs/ntfs: Fix an OOB read when parsing bitmaps for index + attributes + +This fix introduces checks to ensure that bitmaps for directory indices +are never read beyond their actual sizes. + +The lack of this check is a minor issue, likely not exploitable in any way. + +Reported-by: Maxim Suhanov +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 72302033281a..74515114287f 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -839,6 +839,25 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + + if (is_resident) + { ++ if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large"); ++ goto done; ++ } ++ ++ if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range"); ++ goto done; ++ } ++ ++ if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) > ++ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range"); ++ goto done; ++ } ++ + grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14), + bitmap_len); + } diff --git a/0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch b/0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch new file mode 100644 index 00000000..4821d6cb --- /dev/null +++ b/0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:27 +0200 +Subject: [PATCH] fs/ntfs: Fix an OOB read when parsing a volume label + +This fix introduces checks to ensure that an NTFS volume label is always +read from the corresponding file record segment. + +The current NTFS code allows the volume label string to be read from an +arbitrary, attacker-chosen memory location. However, the bytes read are +always treated as UTF-16LE. So, the final string displayed is mostly +unreadable and it can't be easily converted back to raw bytes. + +The lack of this check is a minor issue, likely not causing a significant +data leak. + +Reported-by: Maxim Suhanov +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 74515114287f..32ba8276dd8d 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -1209,13 +1209,29 @@ grub_ntfs_label (grub_device_t device, char **label) + + init_attr (&mft->attr, mft); + pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME); ++ ++ if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); ++ goto fail; ++ } ++ ++ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16) ++ { ++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); ++ goto fail; ++ } ++ + if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) + { + int len; + + len = u32at (pa, 0x10) / 2; + pa += u16at (pa, 0x14); +- *label = get_utf8 (pa, len); ++ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len) ++ *label = get_utf8 (pa, len); ++ else ++ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); + } + + fail: diff --git a/0358-fs-ntfs-Make-code-more-readable.patch b/0358-fs-ntfs-Make-code-more-readable.patch new file mode 100644 index 00000000..dcd1906e --- /dev/null +++ b/0358-fs-ntfs-Make-code-more-readable.patch @@ -0,0 +1,156 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Maxim Suhanov +Date: Tue, 3 Oct 2023 19:12:28 +0200 +Subject: [PATCH] fs/ntfs: Make code more readable + +Move some calls used to access NTFS attribute header fields into +functions with human-readable names. + +Suggested-by: Daniel Kiper +Signed-off-by: Maxim Suhanov +Reviewed-by: Daniel Kiper +--- + grub-core/fs/ntfs.c | 48 +++++++++++++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 15 deletions(-) + +diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c +index 32ba8276dd8d..991b1c2094f5 100644 +--- a/grub-core/fs/ntfs.c ++++ b/grub-core/fs/ntfs.c +@@ -52,6 +52,24 @@ u64at (void *ptr, grub_size_t ofs) + return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs)); + } + ++static grub_uint16_t ++first_attr_off (void *mft_buf_ptr) ++{ ++ return u16at (mft_buf_ptr, 0x14); ++} ++ ++static grub_uint16_t ++res_attr_data_off (void *res_attr_ptr) ++{ ++ return u16at (res_attr_ptr, 0x14); ++} ++ ++static grub_uint32_t ++res_attr_data_len (void *res_attr_ptr) ++{ ++ return u32at (res_attr_ptr, 0x10); ++} ++ + grub_ntfscomp_func_t grub_ntfscomp_func; + + static grub_err_t +@@ -106,7 +124,7 @@ init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) + { + at->mft = mft; + at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0; +- at->attr_nxt = mft->buf + u16at (mft->buf, 0x14); ++ at->attr_nxt = mft->buf + first_attr_off (mft->buf); + at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL; + } + +@@ -154,7 +172,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + return NULL; + } + +- new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)]; ++ new_pos = &at->emft_buf[first_attr_off (at->emft_buf)]; + while (*new_pos != 0xFF) + { + if ((*new_pos == *at->attr_cur) +@@ -213,7 +231,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) + } + else + { +- at->attr_nxt = at->attr_end + u16at (pa, 0x14); ++ at->attr_nxt = at->attr_end + res_attr_data_off (pa); + at->attr_end = at->attr_end + u32at (pa, 4); + pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); + } +@@ -399,20 +417,20 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, + + if (pa[8] == 0) + { +- if (ofs + len > u32at (pa, 0x10)) ++ if (ofs + len > res_attr_data_len (pa)) + return grub_error (GRUB_ERR_BAD_FS, "read out of range"); + +- if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) ++ if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large"); + + if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); + +- if (u16at (pa, 0x14) + u32at (pa, 0x10) > ++ if (res_attr_data_off (pa) + res_attr_data_len (pa) > + (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); + +- grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len); ++ grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len); + return 0; + } + +@@ -556,7 +574,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno) + (unsigned long long) mftno); + + if (!pa[8]) +- mft->size = u32at (pa, 0x10); ++ mft->size = res_attr_data_len (pa); + else + mft->size = u64at (pa, 0x30); + +@@ -801,7 +819,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + (u32at (cur_pos, 0x18) != 0x490024) || + (u32at (cur_pos, 0x1C) != 0x300033)) + continue; +- cur_pos += u16at (cur_pos, 0x14); ++ cur_pos += res_attr_data_off (cur_pos); + if (*cur_pos != 0x30) /* Not filename index */ + continue; + break; +@@ -830,7 +848,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + { + int is_resident = (cur_pos[8] == 0); + +- bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) : ++ bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) : + u32at (cur_pos, 0x28)); + + bmp = grub_malloc (bitmap_len); +@@ -851,14 +869,14 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, + goto done; + } + +- if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) > ++ if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) > + (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos) + { + grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range"); + goto done; + } + +- grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14), ++ grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos), + bitmap_len); + } + else +@@ -1222,12 +1240,12 @@ grub_ntfs_label (grub_device_t device, char **label) + goto fail; + } + +- if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) ++ if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa))) + { + int len; + +- len = u32at (pa, 0x10) / 2; +- pa += u16at (pa, 0x14); ++ len = res_attr_data_len (pa) / 2; ++ pa += res_attr_data_off (pa); + if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len) + *label = get_utf8 (pa, len); + else diff --git a/grub.patches b/grub.patches index e19dc868..e68ab8aa 100644 --- a/grub.patches +++ b/grub.patches @@ -350,3 +350,9 @@ Patch0349: 0349-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch Patch0350: 0350-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch Patch0351: 0351-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch Patch0352: 0352-fs-xfs-Fix-XFS-directory-extent-parsing.patch +Patch0353: 0353-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch +Patch0354: 0354-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch +Patch0355: 0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch +Patch0356: 0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch +Patch0357: 0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch +Patch0358: 0358-fs-ntfs-Make-code-more-readable.patch diff --git a/grub2.spec b/grub2.spec index 4e767f5f..d80dff17 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 118%{?dist} +Release: 119%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -554,6 +554,15 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Mar 8 2024 Nicolas Frayer - 2.06-119 +- GRUB2 NTFS driver vulnerabilities +- (CVE-2023-4692) +- (CVE-2023-4693) +- Resolves: #2236613 +- Resolves: #2241978 +- Resolves: #2241976 +- Resolves: #2238343 + * Wed Feb 7 2024 Nicolas Frayer - 2.06-118 - fs/xfs: Re-applied the XFS directory extent parsing patch - Resolves: #2259266 From a25b6d7a50160e22b14679bb83a1b3d57f5e3bc2 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Mon, 15 Apr 2024 11:05:24 +0200 Subject: [PATCH 26/27] fs/xfs: Handle non-continuous data blocks in directory extents Related: #2254370 Signed-off-by: Nicolas Frayer --- ...n-continuous-data-blocks-in-director.patch | 54 +++++++++++++++++++ grub.patches | 1 + grub2.spec | 6 ++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch diff --git a/0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch b/0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch new file mode 100644 index 00000000..a3ed1a8c --- /dev/null +++ b/0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jon DeVree +Date: Sun, 11 Feb 2024 10:34:58 -0500 +Subject: [PATCH] fs/xfs: Handle non-continuous data blocks in directory + extents + +The directory extent list does not have to be a continuous list of data +blocks. When GRUB tries to read a non-existant member of the list, +grub_xfs_read_file() will return a block of zero'ed memory. Checking for +a zero'ed magic number is sufficient to skip this non-existant data block. + +Prior to commit 07318ee7e (fs/xfs: Fix XFS directory extent parsing) +this was handled as a subtle side effect of reading the (non-existant) +tail data structure. Since the block was zero'ed the computation of the +number of directory entries in the block would return 0 as well. + +Fixes: 07318ee7e (fs/xfs: Fix XFS directory extent parsing) +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2254370 + +Signed-off-by: Jon DeVree +Reviewed-By: Vladimir Serbinenko +Reviewed-by: Daniel Kiper +--- + grub-core/fs/xfs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index bc2224dbb463..8e02ab4a3014 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -902,6 +902,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + grub_xfs_first_de(dir->data, dirblock); + int entries = -1; + char *end = dirblock + dirblk_size; ++ grub_uint32_t magic; + + numread = grub_xfs_read_file (dir, 0, 0, + blk << dirblk_log2, +@@ -912,6 +913,15 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, + return 0; + } + ++ /* ++ * If this data block isn't actually part of the extent list then ++ * grub_xfs_read_file() returns a block of zeros. So, if the magic ++ * number field is all zeros then this block should be skipped. ++ */ ++ magic = *(grub_uint32_t *)(void *) dirblock; ++ if (!magic) ++ continue; ++ + /* + * Leaf and tail information are only in the data block if the number + * of extents is 1. diff --git a/grub.patches b/grub.patches index e68ab8aa..d3eb98da 100644 --- a/grub.patches +++ b/grub.patches @@ -356,3 +356,4 @@ Patch0355: 0355-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch Patch0356: 0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch Patch0357: 0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch Patch0358: 0358-fs-ntfs-Make-code-more-readable.patch +Patch0359: 0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch diff --git a/grub2.spec b/grub2.spec index d80dff17..7e50fd14 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 119%{?dist} +Release: 120%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -554,6 +554,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Apr 12 2024 Nicolas Frayer - 2.06-120 +- fs/xfs: Handle non-continuous data blocks in directory extents +- Related: #2254370 + * Fri Mar 8 2024 Nicolas Frayer - 2.06-119 - GRUB2 NTFS driver vulnerabilities - (CVE-2023-4692) From 6dd575bf565f3f5200aaf63e604829372af0c75d Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Fri, 19 Apr 2024 17:57:13 +0200 Subject: [PATCH 27/27] cmd/search: Rework of CVE-2023-4001 fix Related: #2224951 Resolved: #2263369 Signed-off-by: Nicolas Frayer --- ...d-search-Rework-of-CVE-2023-4001-fix.patch | 180 ++++++++++++++++++ grub.patches | 1 + grub2.spec | 13 +- 3 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 0360-cmd-search-Rework-of-CVE-2023-4001-fix.patch diff --git a/0360-cmd-search-Rework-of-CVE-2023-4001-fix.patch b/0360-cmd-search-Rework-of-CVE-2023-4001-fix.patch new file mode 100644 index 00000000..2c2e628d --- /dev/null +++ b/0360-cmd-search-Rework-of-CVE-2023-4001-fix.patch @@ -0,0 +1,180 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nicolas Frayer +Date: Thu, 16 May 2024 10:58:32 +0200 +Subject: [PATCH] cmd/search: Rework of CVE-2023-4001 fix + +The initial fix implemented a new flag that forces the grub cfg +stub to be located on the same disk as grub. This created several +issues such as RAID machines not being able to boot as their +partition names under grub were different from the partition where +grub is located. It also simply means that any machines with the +/boot partition located on a disk other than the one containing grub +won't boot. +This commit denies booting if the grub cfg stub is located on a USB +drive with a duplicated UUID (UUID being the same as the partition +containing the actual grub cfg stub) + +Signed-off-by: Nicolas Frayer +--- + grub-core/commands/search.c | 134 +++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 126 insertions(+), 8 deletions(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index 4735feefcde5..5956b39dca72 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -30,6 +30,8 @@ + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -54,6 +56,100 @@ struct search_ctx + int is_cache; + }; + ++static int ++is_device_usb (const char *name) ++{ ++ int ret = 0; ++ ++ grub_device_t dev = grub_device_open(name); ++ ++ if (dev) ++ { ++ struct grub_efidisk_data ++ { ++ grub_efi_handle_t handle; ++ grub_efi_device_path_t *device_path; ++ grub_efi_device_path_t *last_device_path; ++ grub_efi_block_io_t *block_io; ++ struct grub_efidisk_data *next; ++ }; ++ ++ if (dev->disk && dev->disk->data) ++ { ++ struct grub_efidisk_data *dp = dev->disk->data; ++ ++ if ( GRUB_EFI_DEVICE_PATH_TYPE (dp->last_device_path) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE && ++ GRUB_EFI_DEVICE_PATH_SUBTYPE (dp->last_device_path) == GRUB_EFI_USB_DEVICE_PATH_SUBTYPE) ++ { ++ ret = 1; ++ } ++ } ++ grub_device_close(dev); ++ } ++ ++ return ret; ++} ++ ++static int ++get_device_uuid(const char *name, char** quid) ++{ ++ int ret = 0; ++ ++ grub_device_t dev_part = grub_device_open(name); ++ ++ if (dev_part) ++ { ++ grub_fs_t fs; ++ ++ fs = grub_fs_probe (dev_part); ++ ++#ifdef DO_SEARCH_FS_UUID ++#define read_fn fs_uuid ++#else ++#define read_fn fs_label ++#endif ++ if (fs && fs->read_fn) ++ { ++ fs->read_fn (dev_part, quid); ++ ++ if (grub_errno == GRUB_ERR_NONE && *quid) ++ { ++ ret = 1; ++ } ++ ++ } ++ grub_device_close (dev_part); ++ } ++ ++ return ret; ++} ++struct uuid_context { ++ char* name; ++ char* uuid; ++}; ++ ++static int ++check_for_duplicate (const char *name, void *data) ++{ ++ int ret = 0; ++ struct uuid_context * uuid_ctx = (struct uuid_context *)data; ++ char *quid = 0; ++ ++ get_device_uuid(name, &quid); ++ ++ if (quid == NULL) ++ return 0; ++ ++ if (!grub_strcasecmp(quid, uuid_ctx->uuid) && grub_strcasecmp(name, uuid_ctx->name)) ++ { ++ ret = 1; ++ } ++ ++ grub_free(quid); ++ ++ return ret; ++} ++ + /* Helper for FUNC_NAME. */ + static int + iterate_device (const char *name, void *data) +@@ -106,14 +202,36 @@ iterate_device (const char *name, void *data) + grub_str_sep (name, name_disk, ',', rem_2); + if (root_disk != NULL && *root_disk != '\0' && + name_disk != NULL && *name_disk != '\0') +- if (grub_strcmp(root_disk, name_disk) != 0) +- { +- grub_free (root_disk); +- grub_free (name_disk); +- grub_free (rem_1); +- grub_free (rem_2); +- return 0; +- } ++ { ++ grub_device_t dev, dev_part; ++ ++ if (is_device_usb(name) && !is_device_usb(root_dev)) ++ { ++ char *quid_name = NULL; ++ int longlist = 0; ++ struct uuid_context uuid_ctx; ++ int ret = 0; ++ ++ get_device_uuid(name, &quid_name); ++ if (!grub_strcmp(quid_name, ctx->key)) ++ { ++ uuid_ctx.name = name; ++ uuid_ctx.uuid = quid_name; ++ ++ ret = grub_device_iterate (check_for_duplicate, &uuid_ctx); ++ ++ if (ret) ++ { ++ grub_printf("Duplicated media UUID found, rebooting ...\n"); ++ grub_sleep(10); ++ grub_reboot(); ++ } ++ } ++ ++ if (quid_name) grub_free (quid_name); ++ ++ } ++ } + } + grub_free (root_disk); + grub_free (name_disk); diff --git a/grub.patches b/grub.patches index d3eb98da..9c41a06d 100644 --- a/grub.patches +++ b/grub.patches @@ -357,3 +357,4 @@ Patch0356: 0356-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch Patch0357: 0357-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch Patch0358: 0358-fs-ntfs-Make-code-more-readable.patch Patch0359: 0359-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch +Patch0360: 0360-cmd-search-Rework-of-CVE-2023-4001-fix.patch diff --git a/grub2.spec b/grub2.spec index 7e50fd14..9135e7e8 100644 --- a/grub2.spec +++ b/grub2.spec @@ -17,7 +17,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 120%{?dist} +Release: 121%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -357,9 +357,11 @@ fi if test ! -f ${EFI_HOME}/grub.cfg; then # there's no config in ESP, create one grub2-mkconfig -o ${EFI_HOME}/grub.cfg + cp -a ${EFI_HOME}/grub.cfg ${EFI_HOME}/grub.cfg.rpmsave + cp -a ${EFI_HOME}/grub.cfg ${GRUB_HOME}/ fi -if ((grep -q "configfile" ${EFI_HOME}/grub.cfg || grep -q "source" ${EFI_HOME}/grub.cfg) && ! grep -q "# It is automatically generated by grub2-mkconfig using templates" ${EFI_HOME}/grub.cfg); then +if (((grep -q "configfile" ${EFI_HOME}/grub.cfg && grep -q "root-dev-only" ${EFI_HOME}/grub.cfg) || grep -q "source" ${EFI_HOME}/grub.cfg) && ! grep -q "# It is automatically generated by grub2-mkconfig using templates" ${EFI_HOME}/grub.cfg); then exit 0 #Already unified fi @@ -379,8 +381,6 @@ if test -f ${EFI_HOME}/grubenv; then mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv fi -cp -a ${EFI_HOME}/grub.cfg ${EFI_HOME}/grub.cfg.rpmsave -cp -a ${EFI_HOME}/grub.cfg ${GRUB_HOME}/ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %files common -f grub.lang @@ -554,6 +554,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Fri Apr 12 2024 Nicolas Frayer - 2.06-121 +- cmd/search: Rework of CVE-2023-4001 fix +- Related: #2224951 +- Resolved: #2263369 + * Fri Apr 12 2024 Nicolas Frayer - 2.06-120 - fs/xfs: Handle non-continuous data blocks in directory extents - Related: #2254370