File 0004-modules-Load-module-sections-at-page-aligned-address.patch of Package grub2
From db7bee2f67310219f7431b28a4b6c1385ac211d3 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Wed, 9 Oct 2024 09:16:39 +0100
Subject: [PATCH 04/13] modules: Load module sections at page-aligned addresses
Currently we load module sections at whatever alignment gcc+ld happened
to dump into the ELF section header which is often less then the page
size. Since NX protections are page based this alignment must be rounded
up to page size on platforms supporting NX protections. This patch
switches EFI platforms to load module sections at 4 KiB page-aligned
addresses. It then changes the allocation size computation and the
loader code in grub_dl_load_segments() to align the locations and sizes
up to these boundaries and fills any added padding with zeros. All of
this happens before relocations are applied, so the relocations factor
that in with no change.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/dl.c | 54 ++++++++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 18 deletions(-)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 6af031072..b384412d1 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -33,6 +33,10 @@
#include <grub/cache.h>
#include <grub/i18n.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/memory.h>
+#endif
+
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
#define GRUB_MODULES_MACHINE_READONLY
@@ -40,10 +44,11 @@
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/sb.h>
+#define DL_ALIGN GRUB_EFI_PAGE_SIZE
+#else
+#define DL_ALIGN 1
#endif
-
-
#pragma GCC diagnostic ignored "-Wcast-align"
grub_dl_t grub_dl_head = 0;
@@ -228,25 +233,34 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
unsigned i;
const Elf_Shdr *s;
- grub_size_t tsize = 0, talign = 1;
+ grub_size_t tsize = 0, talign = 1, arch_addralign = 1;
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__) && !defined (__s390x__)
grub_size_t tramp;
+ grub_size_t tramp_align;
grub_size_t got;
+ grub_size_t got_align;
grub_err_t err;
#endif
char *ptr;
+ arch_addralign = DL_ALIGN;
+
for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff);
i < e->e_shnum;
i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
{
+ grub_size_t sh_addralign;
+ grub_size_t sh_size;
+
if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC))
continue;
- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
- if (talign < s->sh_addralign)
- talign = s->sh_addralign;
+ sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign);
+ sh_size = ALIGN_UP (s->sh_size, sh_addralign);
+
+ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size;
+ talign = grub_max (talign, sh_addralign);
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
@@ -254,12 +268,12 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
if (err)
return err;
- tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
- if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
- talign = GRUB_ARCH_DL_TRAMP_ALIGN;
- tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
- if (talign < GRUB_ARCH_DL_GOT_ALIGN)
- talign = GRUB_ARCH_DL_GOT_ALIGN;
+ tramp_align = grub_max (GRUB_ARCH_DL_TRAMP_ALIGN, arch_addralign);
+ tsize += ALIGN_UP (tramp, tramp_align);
+ talign = grub_max (talign, tramp_align);
+ got_align = grub_max (GRUB_ARCH_DL_GOT_ALIGN, arch_addralign);
+ tsize += ALIGN_UP (got, got_align);
+ talign = grub_max (talign, got_align);
#endif
#ifdef GRUB_MACHINE_EMU
@@ -276,6 +290,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
i < e->e_shnum;
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
{
+ grub_size_t sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign);
+ grub_size_t sh_size = ALIGN_UP (s->sh_size, sh_addralign);
+
if (s->sh_flags & SHF_ALLOC)
{
grub_dl_segment_t seg;
@@ -288,17 +305,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
void *addr;
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign);
addr = ptr;
- ptr += s->sh_size;
+ ptr += sh_size;
switch (s->sh_type)
{
case SHT_PROGBITS:
grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
+ grub_memset ((char *) addr + s->sh_size, 0, sh_size - s->sh_size);
break;
case SHT_NOBITS:
- grub_memset (addr, 0, s->sh_size);
+ grub_memset (addr, 0, sh_size);
break;
}
@@ -307,7 +325,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
else
seg->addr = 0;
- seg->size = s->sh_size;
+ seg->size = sh_size;
seg->section = i;
seg->next = mod->segment;
mod->segment = seg;
@@ -315,11 +333,11 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__) && !defined (__s390x__)
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, tramp_align);
mod->tramp = ptr;
mod->trampptr = ptr;
ptr += tramp;
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, got_align);
mod->got = ptr;
mod->gotptr = ptr;
ptr += got;
--
2.50.1