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
This commit is contained in:
Michael Chang 2021-11-16 01:06:12 +00:00 committed by Git OBS Bridge
parent da8194b45d
commit fb89b0c9e2
4 changed files with 255 additions and 1 deletions

View File

@ -0,0 +1,179 @@
From 10d0f70ac194931c63f2cbd6fdebd6697abae992 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
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 <benh@kernel.crashing.org>
---
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

View File

@ -0,0 +1,66 @@
From 337b3d963d28b3544e8817428fb68ca559613a39 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
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 <pjones@redhat.com>
---
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

View File

@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Nov 11 07:45:11 UTC 2021 - Michael Chang <mchang@suse.com>
- 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 <mchang@suse.com>

View File

@ -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