grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v7 04/10] modules: load module sections at page-aligned addresses


From: Mate Kukri
Subject: [PATCH v7 04/10] modules: load module sections at page-aligned addresses
Date: Fri, 4 Oct 2024 15:41:26 +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 EFI platforms to load module sections at 4kB
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>
---
 grub-core/kern/dl.c | 45 +++++++++++++++++++++++++++++----------------
 include/grub/dl.h   |  9 +++++++++
 2 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 37db9fab0..5dc15f070 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -224,25 +224,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__)
   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_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) && \
@@ -250,12 +259,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
@@ -272,6 +281,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 +296,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;
                }
 
@@ -303,7 +316,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 +324,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/include/grub/dl.h b/include/grub/dl.h
index 750fc8d3d..bd59bb2c4 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -28,6 +28,9 @@
 #include <grub/list.h>
 #include <grub/misc.h>
 #endif
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/memory.h>
+#endif
 
 /*
  * Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules
@@ -308,4 +311,10 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, 
grub_size_t *tramp,
 
 #endif
 
+#ifdef GRUB_MACHINE_EFI
+#define GRUB_DL_ALIGN GRUB_EFI_PAGE_SIZE
+#else
+#define GRUB_DL_ALIGN 1
+#endif
+
 #endif /* ! GRUB_DL_H */
-- 
2.39.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]