From bed013f094b672ffc387c2164ce518f44eaff2be Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 16 Aug 2018 13:51:09 -0400 Subject: [PATCH] Fix arm32 off-by-one error on reading the PE header. Signed-off-by: Peter Jones --- ...m-arm64-loader-better-error-messages.patch | 129 ++++++++++++++++++ ...ernel_header.hdr_offset-be-at-the-ri.patch | 112 +++++++++++++++ grub.patches | 2 + grub2.spec | 3 + 4 files changed, 246 insertions(+) create mode 100644 0230-arm-arm64-loader-better-error-messages.patch create mode 100644 0231-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch diff --git a/0230-arm-arm64-loader-better-error-messages.patch b/0230-arm-arm64-loader-better-error-messages.patch new file mode 100644 index 0000000..d2d7b28 --- /dev/null +++ b/0230-arm-arm64-loader-better-error-messages.patch @@ -0,0 +1,129 @@ +From 8dd7777e4d49ab02a57f4d029afda4944b4773e0 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Aug 2018 14:07:44 -0400 +Subject: [PATCH] arm/arm64 loader: better error messages. + +Signed-off-by: Peter Jones +--- + grub-core/loader/arm64/linux.c | 54 ++++++++++++++++++++++++++-------- + 1 file changed, 41 insertions(+), 13 deletions(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index 93b5cd306eb..3d73861421d 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -70,13 +70,15 @@ finalize_params_linux (void) + { + grub_efi_loaded_image_t *loaded_image = NULL; + int node, retval, len; +- ++ grub_err_t err = GRUB_ERR_NONE; + void *fdt; + + fdt = grub_fdt_load (0x400); +- + if (!fdt) +- goto failure; ++ { ++ err = grub_error(GRUB_ERR_BAD_OS, "failed to load FDT"); ++ goto failure; ++ } + + node = grub_fdt_find_subnode (fdt, 0, "chosen"); + if (node < 0) +@@ -87,17 +89,26 @@ finalize_params_linux (void) + */ + retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Could not find #address-cells"); ++ goto failure; ++ } + + retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Could not find #size-cells"); ++ goto failure; ++ } + + node = grub_fdt_add_subnode (fdt, 0, "chosen"); + } + + if (node < 1) +- goto failure; ++ { ++ err = grub_error(grub_errno, "failed to load chosen fdt node."); ++ goto failure; ++ } + + /* Set initrd info */ + if (initrd_start && initrd_end > initrd_start) +@@ -108,15 +119,26 @@ finalize_params_linux (void) + retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", + initrd_start); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Failed to set linux,initrd-start property"); ++ goto failure; ++ } ++ + retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", + initrd_end); + if (retval) +- goto failure; ++ { ++ err = grub_error(retval, "Failed to set linux,initrd-end property"); ++ goto failure; ++ } + } + +- if (grub_fdt_install() != GRUB_ERR_NONE) +- goto failure; ++ retval = grub_fdt_install(); ++ if (retval != GRUB_ERR_NONE) ++ { ++ err = grub_error(retval, "Failed to install fdt"); ++ goto failure; ++ } + + grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", + fdt); +@@ -124,14 +146,20 @@ finalize_params_linux (void) + /* Convert command line to UCS-2 */ + loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (!loaded_image) +- goto failure; ++ { ++ err = grub_error(grub_errno, "Failed to install fdt"); ++ goto failure; ++ } + + loaded_image->load_options_size = len = + (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); + loaded_image->load_options = + grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); + if (!loaded_image->load_options) +- return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ { ++ err = grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ goto failure; ++ } + + loaded_image->load_options_size = + 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, +@@ -141,7 +169,7 @@ finalize_params_linux (void) + + failure: + grub_fdt_unload(); +- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); ++ return err; + } + + static void +-- +2.17.1 + diff --git a/0231-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch b/0231-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch new file mode 100644 index 0000000..0cb39f9 --- /dev/null +++ b/0231-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch @@ -0,0 +1,112 @@ +From 2d9fe8142b8d470ffe63a23f7788e1c2530401d2 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 16 Aug 2018 11:08:11 -0400 +Subject: [PATCH] Make linux_arm_kernel_header.hdr_offset be at the right place + +The kernel in front of me (slightly edited to make objdump work) looks like: + +00000000 4d 5a 10 13 4d 5a 10 13 4d 5a 10 13 4d 5a 10 13 |MZ..MZ..MZ..MZ..| +00000010 4d 5a 10 13 4d 5a 10 13 4d 5a 10 13 00 00 a0 e1 |MZ..MZ..MZ......| +00000020 f6 03 00 ea 18 28 6f 01 00 00 00 00 00 32 74 00 |.....(o......2t.| +00000030 01 02 03 04 45 45 45 45 74 a2 00 00 40 00 00 00 |....EEEEt...@...| +00000040 50 45 00 00 4c 01 04 00 00 00 00 00 00 00 00 00 |PE..L...........| +00000050 00 00 00 00 90 00 06 03 0b 01 02 14 00 20 74 00 |............. t.| +00000060 00 14 00 00 00 00 00 00 b4 19 00 00 00 10 00 00 |................| +00000070 00 30 74 00 00 00 00 00 00 10 00 00 00 02 00 00 |.0t.............| +00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000090 00 44 74 00 00 10 00 00 00 00 00 00 0a 00 00 00 |.Dt.............| +000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +000000b0 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................| +000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* + +(I don't know why the MZ header is there 7 times, but the offsets work out, so +it's merely a surprising distraction.) + +If linux_arm_kernel_header.reserved2 is 16 bytes, that means hdr_offset is +here: + +00000030 01 02 03 04 45 45 45 45 74 a2 00 00 40 00 00 00 |....EEEEt...@...| +00000040 50 45 00 00 4c 01 04 00 00 00 00 00 00 00 00 00 |PE..L...........| + ^^^^^^^^^^^ + +But it's supposed to be 4 bytes before that. + +This patch makes the reserved field be 3*32 instead of 4*32, and that means we +can find the PE header correcrtly at 0x40 by reading the value at 0x3c. + +Signed-off-by: Peter Jones +--- + grub-core/kern/dl.c | 5 +++++ + grub-core/loader/efi/linux.c | 3 +++ + include/grub/arm/linux.h | 2 +- + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c +index 91105bc4677..3625bd656aa 100644 +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -701,6 +701,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size) + Elf_Ehdr *e; + grub_dl_t mod; + ++ grub_env_set ("debug", "linux,modules,gdb,secureboot"); + grub_dprintf ("modules", "module at %p, size 0x%lx\n", addr, + (unsigned long) size); + e = addr; +@@ -768,6 +769,7 @@ grub_dl_load_core (void *addr, grub_size_t size) + { + grub_dl_t mod; + ++ grub_env_set ("debug", "linux,modules,gdb,secureboot"); + grub_boot_time ("Parsing module"); + + mod = grub_dl_load_core_noinit (addr, size); +@@ -791,6 +793,7 @@ grub_dl_load_file (const char *filename) + void *core = 0; + grub_dl_t mod = 0; + ++ grub_env_set ("debug", "linux,modules,gdb,secureboot"); + #ifdef GRUB_MACHINE_EFI + if (grub_efi_secure_boot ()) + { +@@ -850,6 +853,8 @@ grub_dl_load (const char *name) + grub_dl_t mod; + const char *grub_dl_dir = grub_env_get ("prefix"); + ++ grub_env_set ("debug", "linux,modules,gdb,secureboot"); ++ + mod = grub_dl_get (name); + if (mod) + return mod; +diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c +index 0622dfa48d4..b56ea0bc041 100644 +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -79,7 +79,10 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset, + offset = 512; + #endif + ++ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n", ++ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params); + hf = (handover_func)((char *)kernel_addr + handover_offset + offset); ++ grub_dprintf ("linux", "handover_func() = %p\n", hf); + hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); + + return GRUB_ERR_BUG; +diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h +index 5900fc8a40c..bed308f22cb 100644 +--- a/include/grub/arm/linux.h ++++ b/include/grub/arm/linux.h +@@ -31,7 +31,7 @@ struct linux_arm_kernel_header { + grub_uint32_t magic; + grub_uint32_t start; /* _start */ + grub_uint32_t end; /* _edata */ +- grub_uint32_t reserved2[4]; ++ grub_uint32_t reserved2[3]; + grub_uint32_t hdr_offset; + }; + +-- +2.17.1 + diff --git a/grub.patches b/grub.patches index 1052af9..573ebf4 100644 --- a/grub.patches +++ b/grub.patches @@ -227,3 +227,5 @@ Patch0226: 0226-Make-efi_netfs-not-duplicate-symbols-from-efinet.patch Patch0227: 0227-Rework-how-the-fdt-command-builds.patch Patch0228: 0228-Disable-non-wordsize-allocations-on-arm.patch Patch0229: 0229-strip-R-.note.gnu.property-at-more-places.patch +Patch0230: 0230-arm-arm64-loader-better-error-messages.patch +Patch0231: 0231-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch diff --git a/grub2.spec b/grub2.spec index cbffd1b..b42e619 100644 --- a/grub2.spec +++ b/grub2.spec @@ -499,6 +499,9 @@ fi %endif %changelog +* Thu Aug 16 2018 Peter Jones - 2.02-50 +- Fix arm32 off-by-one error on reading the PE header. + * Tue Aug 14 2018 Peter Jones - 2.02-50 - Fix typo in /etc/grub.d/01_fallback_counting Resolves: rhbz#1614637