[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 04/10] modules: load module sections at page-aligned addresses
From: |
Mate Kukri |
Subject: |
[PATCH v4 04/10] modules: load module sections at page-aligned addresses |
Date: |
Wed, 12 Jun 2024 16:57:07 +0100 |
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 most EFI platforms to load module sections at 4kB
page-aligned addresses. To do so, it adds an new per-arch function,
grub_arch_dl_min_alignment(), which returns the alignment needed for
dynamically loaded sections (in bytes). Currently it sets it to 4096
when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and
1-byte alignment on everything else.
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.
Original-Author: Peter Jones <pjones@redhat.com>
Original-Author: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
---
docs/grub-dev.texi | 6 ++---
grub-core/kern/arm/dl.c | 13 +++++++++
grub-core/kern/arm64/dl.c | 13 +++++++++
grub-core/kern/dl.c | 53 ++++++++++++++++++++++++++-----------
grub-core/kern/emu/full.c | 13 +++++++++
grub-core/kern/i386/dl.c | 13 +++++++++
grub-core/kern/ia64/dl.c | 9 +++++++
grub-core/kern/mips/dl.c | 8 ++++++
grub-core/kern/powerpc/dl.c | 9 +++++++
grub-core/kern/riscv/dl.c | 13 +++++++++
grub-core/kern/sparc64/dl.c | 9 +++++++
grub-core/kern/x86_64/dl.c | 13 +++++++++
include/grub/dl.h | 2 ++
13 files changed, 155 insertions(+), 19 deletions(-)
diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index 1276c5930..2f782cda5 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -996,9 +996,9 @@ declare startup asm file ($cpu_$platform_startup) as well
as any other files
(e.g. init.c and callwrap.S) (e.g. $cpu_$platform =
kern/$cpu/$platform/init.c).
At this stage you will also need to add dummy dl.c and cache.S with functions
grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t
-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and
-void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They
-won't be used for now.
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t
+grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void
+*address, grub_size_t len) (cache.S). They won't be used for now.
You will need to create directory include/$cpu/$platform and a file
include/$cpu/types.h. The latter following this template:
diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c
index eab9d17ff..926073793 100644
--- a/grub-core/kern/arm/dl.c
+++ b/grub-core/kern/arm/dl.c
@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr)
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c
index a2b5789a9..95c6d5bf4 100644
--- a/grub-core/kern/arm64/dl.c
+++ b/grub-core/kern/arm64/dl.c
@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 37db9fab0..8338f7436 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -224,25 +224,35 @@ 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__)
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 = grub_arch_dl_min_alignment ();
+
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;
+ if (talign < sh_addralign)
+ talign = sh_addralign;
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
@@ -250,12 +260,18 @@ 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_ARCH_DL_TRAMP_ALIGN;
+ if (tramp_align < arch_addralign)
+ tramp_align = arch_addralign;
+ tsize += ALIGN_UP (tramp, tramp_align);
+ if (talign < tramp_align)
+ talign = tramp_align;
+ got_align = GRUB_ARCH_DL_GOT_ALIGN;
+ if (got_align < arch_addralign)
+ got_align = arch_addralign;
+ tsize += ALIGN_UP (got, got_align);
+ if (talign < got_align)
+ talign = got_align;
#endif
#ifdef GRUB_MACHINE_EMU
@@ -272,6 +288,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;
@@ -284,17 +303,19 @@ 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;
}
@@ -303,7 +324,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;
@@ -311,11 +332,11 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__)
- 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;
diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c
index e8d63b1f5..1de1c28eb 100644
--- a/grub-core/kern/emu/full.c
+++ b/grub-core/kern/emu/full.c
@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void)
}
#endif
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c
index 1346da5cc..d6b4681fc 100644
--- a/grub-core/kern/i386/dl.c
+++ b/grub-core/kern/i386/dl.c
@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c
index db59300fe..92d82c575 100644
--- a/grub-core/kern/ia64/dl.c
+++ b/grub-core/kern/ia64/dl.c
@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
}
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+ return 1;
+}
diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c
index 5b02f97fc..db411899d 100644
--- a/grub-core/kern/mips/dl.c
+++ b/grub-core/kern/mips/dl.c
@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void)
grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0);
}
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+ return 1;
+}
diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c
index 7b6418eab..0eb8bc5bd 100644
--- a/grub-core/kern/powerpc/dl.c
+++ b/grub-core/kern/powerpc/dl.c
@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+ return 1;
+}
diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c
index 896653bb4..1fa085b4a 100644
--- a/grub-core/kern/riscv/dl.c
+++ b/grub-core/kern/riscv/dl.c
@@ -344,3 +344,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c
index f3d960186..f054f0824 100644
--- a/grub-core/kern/sparc64/dl.c
+++ b/grub-core/kern/sparc64/dl.c
@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+ return 1;
+}
diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c
index e5a8bdcf4..a105dc50c 100644
--- a/grub-core/kern/x86_64/dl.c
+++ b/grub-core/kern/x86_64/dl.c
@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
return GRUB_ERR_NONE;
}
+
+/*
+ * Tell the loader what our minimum section alignment is.
+ */
+grub_size_t
+grub_arch_dl_min_alignment (void)
+{
+#ifdef GRUB_MACHINE_EFI
+ return 4096;
+#else
+ return 1;
+#endif
+}
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 750fc8d3d..8a37cc16f 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -264,6 +264,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr);
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
Elf_Shdr *s, grub_dl_segment_t seg);
+grub_size_t
+grub_arch_dl_min_alignment (void);
#endif
#if defined (_mips)
--
2.39.2
- Re: [PATCH v4 06/10] nx: set page permissions for loaded modules., (continued)
- [PATCH v4 02/10] modules: strip .llvm_addrsig sections and similar., Mate Kukri, 2024/06/12
- [PATCH v4 01/10] modules: make .module_license read-only, Mate Kukri, 2024/06/12
- [PATCH v4 03/10] modules: Don't allocate space for non-allocable sections., Mate Kukri, 2024/06/12
- [PATCH v4 05/10] nx: add memory attribute get/set API, Mate Kukri, 2024/06/12
- [PATCH v4 10/10] efi: Disallow fallback to legacy Linux loader when shim says NX is required., Mate Kukri, 2024/06/12
- [PATCH v4 04/10] modules: load module sections at page-aligned addresses,
Mate Kukri <=
- [PATCH v4 07/10] nx: set the nx compatible flag in EFI grub images, Mate Kukri, 2024/06/12
- [PATCH v4 08/10] efi: Provide wrappers for load_image, start_image, unload_image, Mate Kukri, 2024/06/12
- [PATCH v4 09/10] efi: Use shim's loader protocol for EFI image verification and loading, Mate Kukri, 2024/06/12
- Re: [PATCH v4 00/10] UEFI NX support and NX Linux loader using shim loader protocol, Daniel Kiper, 2024/06/25