From fb89b0c9e285aa28dba6bb99de8c1f96e78a1bd00e4b9eeb196c35bf6ed4fff6 Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Tue, 16 Nov 2021 01:06:12 +0000 Subject: [PATCH] Accepting request 931473 from home:michael-chang:bsc:1192522 - Fix arm64 kernel image not aligned on 64k boundary (bsc#1192522) * 0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch * 0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch OBS-URL: https://build.opensuse.org/request/show/931473 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=397 --- ...x-EFI-loader-kernel-image-allocation.patch | 179 ++++++++++++++++++ ...r-the-PE-magic-for-the-compiled-arch.patch | 66 +++++++ grub2.changes | 7 + grub2.spec | 4 +- 4 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch create mode 100644 0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch diff --git a/0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch b/0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch new file mode 100644 index 0000000..d7305ab --- /dev/null +++ b/0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch @@ -0,0 +1,179 @@ +From 10d0f70ac194931c63f2cbd6fdebd6697abae992 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Mon, 2 Aug 2021 23:10:01 +1000 +Subject: [PATCH 1/2] arm64: Fix EFI loader kernel image allocation + +We are currently allocating just enough memory for the file size, +which means that the kernel BSS is in limbo (and not even zeroed). + +We are also not honoring the alignment specified in the image +PE header. + +This makes us use the PE optional header in which the kernel puts the +actual size it needs, including BSS, and make sure we clear it, and +honors the specified alignment for the image. + +Signed-off-by: Benjamin Herrenschmidt +--- + grub-core/loader/arm64/efi/linux.c | 92 ++++++++++++++++++++---------- + 1 file changed, 63 insertions(+), 29 deletions(-) + +diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c +index b73105347..4da49a182 100644 +--- a/grub-core/loader/arm64/efi/linux.c ++++ b/grub-core/loader/arm64/efi/linux.c +@@ -39,6 +39,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; + static int loaded; + ++static void *kernel_alloc_addr; ++static grub_uint32_t kernel_alloc_pages; + static void *kernel_addr; + static grub_uint64_t kernel_size; + static grub_uint32_t handover_offset; +@@ -258,9 +260,8 @@ grub_linux_unload (void) + GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); + initrd_start = initrd_end = 0; + grub_free (linux_args); +- if (kernel_addr) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + grub_fdt_unload (); + return GRUB_ERR_NONE; + } +@@ -365,14 +366,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + return grub_errno; + } + ++static grub_err_t ++parse_pe_header (void *kernel, grub_uint64_t *total_size, ++ grub_uint32_t *entry_offset, ++ grub_uint32_t *alignment) ++{ ++ struct linux_arch_kernel_header *lh = kernel; ++ struct grub_armxx_linux_pe_header *pe; ++ ++ pe = (void *)((unsigned long)kernel + lh->hdr_offset); ++ ++ if (pe->opt.magic != GRUB_PE32_PE64_MAGIC) ++ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); ++ ++ *total_size = pe->opt.image_size; ++ *entry_offset = pe->opt.entry_addr; ++ *alignment = pe->opt.section_alignment; ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- struct linux_arch_kernel_header lh; +- struct grub_armxx_linux_pe_header *pe; + grub_err_t err; ++ grub_off_t filelen; ++ grub_uint32_t align = 0; ++ void *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -386,39 +408,49 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (!file) + goto fail; + +- kernel_size = grub_file_size (file); ++ filelen = grub_file_size (file); ++ kernel = grub_malloc(filelen); ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer")); ++ goto fail; ++ } + +- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) +- return grub_errno; ++ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen) ++ { ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), ++ argv[0]); ++ goto fail; ++ } + +- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) ++ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); ++ ++ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE) ++ goto fail; ++ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE) + goto fail; ++ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size); ++ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset); ++ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align); + + grub_loader_unset(); + +- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); +- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- grub_dprintf ("linux", "kernel numpages: %lld\n", +- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); +- if (!kernel_addr) ++ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); ++ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); ++ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages); ++ if (!kernel_alloc_addr) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + goto fail; + } +- +- grub_file_seek (file, 0); +- if (grub_file_read (file, kernel_addr, kernel_size) +- < (grub_int64_t) kernel_size) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); +- goto fail; +- } ++ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align); + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); +- +- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); +- handover_offset = pe->opt.entry_addr; ++ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size)); ++ if (kernel_size > filelen) ++ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen); ++ grub_free(kernel); ++ kernel = NULL; + + cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); + linux_args = grub_malloc (cmdline_size); +@@ -442,6 +474,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + fail: ++ if (kernel) ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + +@@ -454,9 +489,8 @@ fail: + if (linux_args && !loaded) + grub_free (linux_args); + +- if (kernel_addr && !loaded) +- grub_efi_free_pages ((grub_addr_t) kernel_addr, +- GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ if (kernel_alloc_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages); + + return grub_errno; + } +-- +2.31.1 + diff --git a/0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch b/0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch new file mode 100644 index 0000000..6e49e42 --- /dev/null +++ b/0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch @@ -0,0 +1,66 @@ +From 337b3d963d28b3544e8817428fb68ca559613a39 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 9 Sep 2021 10:59:28 -0400 +Subject: [PATCH 2/2] Arm: check for the PE magic for the compiled arch + +In "arm64: Fix EFI loader kernel image allocation", Ben fixed the kernel +alignment to match the alignment given in the PE header. In doing so, a +check for valid PE magic was added, which was hard-coded to the value +seen on Aarch64 (GRUB_PE32_PE64_MAGIC). + +Unfortunately, this code is shared between 64-bit and 32-bit, and so +that value broke 32-bit Arm systems. + +This patch adds a constant definition for GRUB_PE32_PEXX_MAGIC, which is +either GRUB_PE32_PE64_MAGIC or GRUB_PE32_PE32_MAGIC, depending on which +platform is being built, and uses it in the header magic check. + +Resolves: rhbz#2000756 + +Signed-off-by: Peter Jones +--- + grub-core/loader/arm64/efi/linux.c | 2 +- + include/grub/arm/linux.h | 1 + + include/grub/arm64/linux.h | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c +index 4da49a182..87cb2f97c 100644 +--- a/grub-core/loader/arm64/efi/linux.c ++++ b/grub-core/loader/arm64/efi/linux.c +@@ -376,7 +376,7 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size, + + pe = (void *)((unsigned long)kernel + lh->hdr_offset); + +- if (pe->opt.magic != GRUB_PE32_PE64_MAGIC) ++ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC) + return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic"); + + *total_size = pe->opt.image_size; +diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h +index b582f67f6..966a5074f 100644 +--- a/include/grub/arm/linux.h ++++ b/include/grub/arm/linux.h +@@ -44,6 +44,7 @@ struct grub_arm_linux_pe_header + + #if defined(__arm__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC + # define linux_arch_kernel_header linux_arm_kernel_header + # define grub_armxx_linux_pe_header grub_arm_linux_pe_header + #endif +diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h +index de99d39c0..b4b91473a 100644 +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -48,6 +48,7 @@ struct grub_arm64_linux_pe_header + + #if defined(__aarch64__) + # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE ++# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC + # define linux_arch_kernel_header linux_arm64_kernel_header + # define grub_armxx_linux_pe_header grub_arm64_linux_pe_header + #endif +-- +2.31.1 + diff --git a/grub2.changes b/grub2.changes index 0ff454a..2110cd7 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Nov 11 07:45:11 UTC 2021 - Michael Chang + +- Fix arm64 kernel image not aligned on 64k boundary (bsc#1192522) + * 0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch + * 0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch + ------------------------------------------------------------------- Thu Oct 21 12:51:46 UTC 2021 - Michael Chang diff --git a/grub2.spec b/grub2.spec index e592d55..577788e 100644 --- a/grub2.spec +++ b/grub2.spec @@ -312,6 +312,8 @@ Patch794: 0001-Filter-out-POSIX-locale-for-translation.patch Patch795: 0001-ieee1275-implement-FCP-methods-for-WWPN-and-LUNs.patch Patch796: 0001-disk-diskfilter-Use-nodes-in-logical-volume-s-segmen.patch Patch797: 0001-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch +Patch798: 0001-arm64-Fix-EFI-loader-kernel-image-allocation.patch +Patch799: 0002-Arm-check-for-the-PE-magic-for-the-compiled-arch.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -329,8 +331,8 @@ Requires: grub2-%{grubarch} = %{version}-%{release} %ifarch s390x # required utilities by grub2-s390x-04-grub2-install.patch # use 'showconsole' to determine console device. (bnc#876743) -Requires: (/sbin/showconsole or /usr/sbin/showconsole) Requires: kexec-tools +Requires: (/sbin/showconsole or /usr/sbin/showconsole) # for /sbin/zipl used by grub2-zipl-setup Requires: s390-tools %endif