grub-devel
[Top][All Lists]
Advanced

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

[PATCH 2/6] elf: Validate number of elf section header table entries


From: Alec Brown
Subject: [PATCH 2/6] elf: Validate number of elf section header table entries
Date: Thu, 26 May 2022 15:29:48 -0400

In bsdXX.c and multiboot_elfXX.c, e_shnum is used to obtain the number of
section header table entries, but it wasn't being checked if the value was
there.

According to the elf(5) manual page,
"If the number of entries in the section header table is larger than or equal to
SHN_LORESERVE (0xff00), e_shnum holds the value zero and the real number of
entries in the section header table is held in the sh_size member of the intial
entry in section header table. Otherwise, the sh_size member of the initial
entry in the section header table holds the value zero."

Since this check wasn't being made, grub_elfXX_get_shnum() is being added to
elfXX.c to make this check and use whichever member doesn't have a value of
zero. If both are zero, then we must return an error. We also need to make sure
that e_shnum doesn't have a value greater than or equal to SHN_LORESERVE and
sh_size isn't less than SHN_LORESERVE.

In order to get this function to work, the type ElfXX_Shnum is being added where
Elf32_Shnum defines Elf32_Word and Elf64_Shnum defines Elf64_Xword. This new
type is needed because if shnum obtains a value from sh_size, sh_size could be
of type El32_Word for Elf32_Shdr structures or Elf64_Xword for Elf64_Shdr
structures.

Note that even though elf.c and elfXX.c are located in grub-core/kern, they are
compiled as modules and don't need the EXPORT_FUNC macro to define the functions
in elf.h.

Also, changed casts of shnum to match variables being set as well as dropped
casts when unnecessary and fixed spacing errors in bsdXX.c.

Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
---
 grub-core/kern/elf.c               | 12 +++++
 grub-core/kern/elfXX.c             | 34 +++++++++++++
 grub-core/loader/i386/bsdXX.c      | 82 ++++++++++++++++++++++--------
 grub-core/loader/multiboot_elfxx.c | 49 +++++++++++-------
 include/grub/elf.h                 | 14 +++++
 5 files changed, 150 insertions(+), 41 deletions(-)

diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c
index 9d7149b38..66b69293e 100644
--- a/grub-core/kern/elf.c
+++ b/grub-core/kern/elf.c
@@ -167,11 +167,15 @@ grub_elf_open (const char *name, enum grub_file_type type)
 #define grub_elfXX_load_phdrs grub_elf32_load_phdrs
 #define ElfXX_Phdr Elf32_Phdr
 #define ElfXX_Ehdr Elf32_Ehdr
+#define ElfXX_Shdr Elf32_Shdr
+#define ElfXX_Word Elf32_Word
+#define ElfXX_Shnum Elf32_Shnum
 #define grub_uintXX_t grub_uint32_t
 #define grub_swap_bytes_addrXX grub_swap_bytes32
 #define grub_swap_bytes_offXX grub_swap_bytes32
 #define grub_swap_bytes_XwordXX grub_swap_bytes32
 #define grub_elfXX_check_endianess_and_bswap_ehdr 
grub_elf32_check_endianess_and_bswap_ehdr
+#define grub_elfXX_get_shnum grub_elf32_get_shnum
 
 #include "elfXX.c"
 
@@ -185,11 +189,15 @@ grub_elf_open (const char *name, enum grub_file_type type)
 #undef grub_elfXX_load_phdrs
 #undef ElfXX_Phdr
 #undef ElfXX_Ehdr
+#undef ElfXX_Shdr
+#undef ElfXX_Word
+#undef ElfXX_Shnum
 #undef grub_uintXX_t
 #undef grub_swap_bytes_addrXX
 #undef grub_swap_bytes_offXX
 #undef grub_swap_bytes_XwordXX
 #undef grub_elfXX_check_endianess_and_bswap_ehdr
+#undef grub_elfXX_get_shnum
 
 
 /* 64-bit */
@@ -203,10 +211,14 @@ grub_elf_open (const char *name, enum grub_file_type type)
 #define grub_elfXX_load_phdrs grub_elf64_load_phdrs
 #define ElfXX_Phdr Elf64_Phdr
 #define ElfXX_Ehdr Elf64_Ehdr
+#define ElfXX_Shdr Elf64_Shdr
+#define ElfXX_Word Elf64_Word
+#define ElfXX_Shnum Elf64_Shnum
 #define grub_uintXX_t grub_uint64_t
 #define grub_swap_bytes_addrXX grub_swap_bytes64
 #define grub_swap_bytes_offXX grub_swap_bytes64
 #define grub_swap_bytes_XwordXX grub_swap_bytes64
 #define grub_elfXX_check_endianess_and_bswap_ehdr 
grub_elf64_check_endianess_and_bswap_ehdr
+#define grub_elfXX_get_shnum grub_elf64_get_shnum
 
 #include "elfXX.c"
diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c
index 1859d1880..48b7745a5 100644
--- a/grub-core/kern/elfXX.c
+++ b/grub-core/kern/elfXX.c
@@ -205,3 +205,37 @@ grub_elfXX_check_endianess_and_bswap_ehdr (grub_elf_t elf)
 
   return 0;
 }
+
+grub_err_t
+grub_elfXX_get_shnum (ElfXX_Ehdr *e, ElfXX_Shnum *shnum)
+{
+  ElfXX_Shdr *s;
+
+  if (shnum == NULL)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for 
shnum"));
+
+  /* Set *shnum to 0 so that shnum doesn't return junk on error */
+  *shnum = 0;
+
+  if (e == NULL)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for elf 
header"));
+
+  *shnum = e->e_shnum;
+  if (*shnum == SHN_UNDEF)
+    {
+      if (e->e_shoff == 0)
+       return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header 
table offset in e_shoff"));
+
+      s = (ElfXX_Shdr *) ((grub_uint8_t *) e + e->e_shoff);
+      *shnum = s->sh_size;
+      if (*shnum < SHN_LORESERVE)
+       return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section 
header table entries in sh_size: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum);
+    }
+  else
+    {
+      if (*shnum >= SHN_LORESERVE)
+       return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section 
header table entries in e_shnum: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum);
+    }
+
+  return GRUB_ERR_NONE;
+}
diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c
index e6edc6fb6..6e5eb3643 100644
--- a/grub-core/loader/i386/bsdXX.c
+++ b/grub-core/loader/i386/bsdXX.c
@@ -26,7 +26,10 @@ load (grub_file_t file, const char *filename, void *where, 
grub_off_t off, grub_
 static inline grub_err_t
 read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, Elf_Shdr 
**shdr)
 {
- if (grub_file_seek (file, 0) == (grub_off_t) -1)
+  Elf_Shnum shnum;
+  grub_err_t err;
+
+  if (grub_file_seek (file, 0) == (grub_off_t) -1)
     return grub_errno;
 
   if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
@@ -48,15 +51,19 @@ read_headers (grub_file_t file, const char *filename, 
Elf_Ehdr *e, Elf_Shdr **sh
   if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
     return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF 
magic"));
 
-  *shdr = grub_calloc (e->e_shnum, e->e_shentsize);
+  err = grub_elf_get_shnum (e, &shnum);
+  if (err)
+    return err;
+
+  *shdr = grub_calloc (shnum, e->e_shentsize);
   if (! *shdr)
     return grub_errno;
 
   if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
     return grub_errno;
 
-  if (grub_file_read (file, *shdr, (grub_uint32_t) e->e_shnum * e->e_shentsize)
-      != (grub_ssize_t) ((grub_uint32_t) e->e_shnum * e->e_shentsize))
+  if (grub_file_read (file, *shdr, shnum * e->e_shentsize)
+      != ((grub_ssize_t) shnum * e->e_shentsize))
     {
       if (grub_errno)
        return grub_errno;
@@ -78,6 +85,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct 
grub_relocator *relocator,
 {
   Elf_Ehdr e;
   Elf_Shdr *s, *shdr = NULL;
+  Elf_Shnum shnum;
   grub_addr_t curload, module;
   grub_err_t err;
   grub_size_t chunk_size = 0;
@@ -89,7 +97,11 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct 
grub_relocator *relocator,
   if (err)
     goto out;
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  err = grub_elf_get_shnum (&e, &shnum);
+  if (err != GRUB_ERR_NONE)
+    goto out;
+
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
     {
       if (s->sh_size == 0)
@@ -111,7 +123,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct 
grub_relocator *relocator,
     chunk_src = get_virtual_current_address (ch);
   }
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
     {
       if (s->sh_size == 0)
@@ -154,7 +166,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct 
grub_relocator *relocator,
   if (! err)
     err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
                             | FREEBSD_MODINFOMD_SHDR,
-                            shdr, e.e_shnum * e.e_shentsize);
+                            shdr, shnum * e.e_shentsize);
 
 out:
   grub_free (shdr);
@@ -170,6 +182,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator 
*relocator,
 {
   Elf_Ehdr e;
   Elf_Shdr *s, *shdr = NULL;
+  Elf_Shnum shnum;
   grub_addr_t curload, module;
   grub_err_t err;
   grub_size_t chunk_size = 0;
@@ -181,7 +194,11 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct 
grub_relocator *relocator,
   if (err)
     goto out;
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  err = grub_elf_get_shnum (&e, &shnum);
+  if (err != GRUB_ERR_NONE)
+    goto out;
+
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
     {
       if (s->sh_size == 0)
@@ -196,7 +213,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator 
*relocator,
   if (chunk_size < sizeof (e))
     chunk_size = sizeof (e);
   chunk_size += (grub_uint32_t) e.e_phnum * e.e_phentsize;
-  chunk_size += (grub_uint32_t) e.e_shnum * e.e_shentsize;
+  chunk_size += (grub_size_t) shnum * e.e_shentsize;
 
   {
     grub_relocator_chunk_t ch;
@@ -209,7 +226,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator 
*relocator,
     chunk_src = get_virtual_current_address (ch);
   }
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
     {
       if (s->sh_size == 0)
@@ -247,9 +264,9 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator 
*relocator,
     curload = module + sizeof (e);
 
   load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, 
e.e_shoff,
-       (grub_uint32_t) e.e_shnum * e.e_shentsize);
+       (grub_size_t) shnum * e.e_shentsize);
   e.e_shoff = curload - module;
-  curload +=  (grub_uint32_t) e.e_shnum * e.e_shentsize;
+  curload +=  (grub_addr_t) shnum * e.e_shentsize;
 
   load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, 
e.e_phoff,
        (grub_uint32_t) e.e_phnum * e.e_phentsize);
@@ -279,6 +296,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator 
*relocator,
   grub_err_t err;
   Elf_Ehdr e;
   Elf_Shdr *s, *shdr = NULL;
+  Elf_Shnum shnum;
   unsigned symoff, stroff, symsize, strsize;
   grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
   Elf_Sym *sym;
@@ -293,17 +311,21 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct 
grub_relocator *relocator,
   if (err)
     goto out;
 
+  err = grub_elf_get_shnum (&e, &shnum);
+  if (err != GRUB_ERR_NONE)
+    goto out;
+
   err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
                           FREEBSD_MODINFOMD_ELFHDR, &e,
                           sizeof (e));
   if (err)
     goto out;
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
       if (s->sh_type == SHT_SYMTAB)
        break;
-  if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+  if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
     {
       err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table"));
       goto out;
@@ -418,6 +440,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator 
*relocator,
   grub_err_t err;
   Elf_Ehdr e;
   Elf_Shdr *s, *symsh, *strsh, *shdr = NULL;
+  Elf_Shnum shnum;
   unsigned symsize, strsize;
   void *sym_chunk;
   grub_uint8_t *curload;
@@ -433,11 +456,18 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator 
*relocator,
       return grub_errno;
     }
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  err = grub_elf_get_shnum (&e, &shnum);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_free (shdr);
+      return err;
+    }
+
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
       if (s->sh_type == SHT_SYMTAB)
        break;
-  if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+  if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
     {
       grub_free (shdr);
       return GRUB_ERR_NONE;
@@ -450,7 +480,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator 
*relocator,
 
   chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
     + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
-    + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+    + sizeof (e) + shnum * e.e_shentsize;
 
   symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
   {
@@ -478,17 +508,17 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator 
*relocator,
 
   curload += sizeof (e);
 
-  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+  for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
        s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
     {
       Elf_Shdr *s2;
       s2 = (Elf_Shdr *) curload;
       grub_memcpy (curload, s, e.e_shentsize);
       if (s == symsh)
-       s2->sh_offset = sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+       s2->sh_offset = sizeof (e) + shnum * e.e_shentsize;
       else if (s == strsh)
        s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
-         + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+         + sizeof (e) + shnum * e.e_shentsize;
       else
        s2->sh_offset = 0;
       s2->sh_addr = s2->sh_offset;
@@ -552,6 +582,7 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
     grub_err_t err;
     Elf_Ehdr e;
     Elf_Shdr *s, *shdr = NULL;
+    Elf_Shnum shnum;
 
     err = read_headers (file, filename, &e, &shdr);
     if (err)
@@ -560,11 +591,18 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
        return err;
       }
 
-    for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * 
e.e_shentsize);
+    err = grub_elf_get_shnum (&e, &shnum);
+    if (err != GRUB_ERR_NONE)
+      {
+       grub_free (shdr);
+       return err;
+      }
+
+    for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * 
e.e_shentsize);
         s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
       if (s->sh_type == SHT_SYMTAB)
        break;
-    if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+    if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
       {
        grub_free (shdr);
        return GRUB_ERR_NONE;
diff --git a/grub-core/loader/multiboot_elfxx.c 
b/grub-core/loader/multiboot_elfxx.c
index 6801f0ddf..0d6b6612f 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -17,19 +17,23 @@
  */
 
 #if defined(MULTIBOOT_LOAD_ELF32)
-# define XX            32
-# define E_MACHINE     MULTIBOOT_ELF32_MACHINE
-# define ELFCLASSXX    ELFCLASS32
-# define Elf_Ehdr      Elf32_Ehdr
-# define Elf_Phdr      Elf32_Phdr
-# define Elf_Shdr      Elf32_Shdr
+# define XX                    32
+# define E_MACHINE             MULTIBOOT_ELF32_MACHINE
+# define ELFCLASSXX            ELFCLASS32
+# define Elf_Ehdr              Elf32_Ehdr
+# define Elf_Phdr              Elf32_Phdr
+# define Elf_Shdr              Elf32_Shdr
+# define Elf_Shnum             Elf32_Shnum
+# define grub_elf_get_shnum    grub_elf32_get_shnum
 #elif defined(MULTIBOOT_LOAD_ELF64)
-# define XX            64
-# define E_MACHINE     MULTIBOOT_ELF64_MACHINE
-# define ELFCLASSXX    ELFCLASS64
-# define Elf_Ehdr      Elf64_Ehdr
-# define Elf_Phdr      Elf64_Phdr
-# define Elf_Shdr      Elf64_Shdr
+# define XX                    64
+# define E_MACHINE             MULTIBOOT_ELF64_MACHINE
+# define ELFCLASSXX            ELFCLASS64
+# define Elf_Ehdr              Elf64_Ehdr
+# define Elf_Phdr              Elf64_Phdr
+# define Elf_Shdr              Elf64_Shdr
+# define Elf_Shnum             Elf64_Shnum
+# define grub_elf_get_shnum    grub_elf64_get_shnum
 #else
 #error "I'm confused"
 #endif
@@ -58,7 +62,8 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
   grub_err_t err;
   grub_relocator_chunk_t ch;
   grub_uint32_t load_offset = 0, load_size;
-  int i;
+  Elf_Shnum shnum;
+  unsigned int i;
   void *source = NULL;
 
   if (ehdr->e_ident[EI_MAG0] != ELFMAG0
@@ -75,6 +80,10 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
   if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
     return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the 
right type"));
 
+  err = grub_elf_get_shnum (ehdr, &shnum);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
   /* FIXME: Should we support program headers at strange locations?  */
   if (ehdr->e_phoff + (grub_uint32_t) ehdr->e_phnum * ehdr->e_phentsize > 
MULTIBOOT_SEARCH)
     return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
@@ -213,11 +222,11 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 #error Please complete this
 #endif
 
-  if (ehdr->e_shnum)
+  if (shnum)
     {
       grub_uint8_t *shdr, *shdrptr;
 
-      shdr = grub_calloc (ehdr->e_shnum, ehdr->e_shentsize);
+      shdr = grub_calloc (shnum, ehdr->e_shentsize);
       if (!shdr)
        return grub_errno;
 
@@ -227,8 +236,8 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
          return grub_errno;
        }
 
-      if (grub_file_read (mld->file, shdr, (grub_uint32_t) ehdr->e_shnum * 
ehdr->e_shentsize)
-              != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
+      if (grub_file_read (mld->file, shdr, shnum * ehdr->e_shentsize)
+              != (grub_ssize_t) shnum * ehdr->e_shentsize)
        {
          if (!grub_errno)
            grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file 
%s"),
@@ -236,7 +245,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
          return grub_errno;
        }
 
-      for (shdrptr = shdr, i = 0; i < ehdr->e_shnum;
+      for (shdrptr = shdr, i = 0; i < shnum;
           shdrptr += ehdr->e_shentsize, i++)
        {
          Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
@@ -281,7 +290,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
            }
          sh->sh_addr = target;
        }
-      GRUB_MULTIBOOT (add_elfsyms) (ehdr->e_shnum, ehdr->e_shentsize,
+      GRUB_MULTIBOOT (add_elfsyms) (shnum, ehdr->e_shentsize,
                                    ehdr->e_shstrndx, shdr);
     }
 
@@ -296,3 +305,5 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 #undef Elf_Ehdr
 #undef Elf_Phdr
 #undef Elf_Shdr
+#undef Elf_Shnum
+#undef grub_elf_get_shnum
diff --git a/include/grub/elf.h b/include/grub/elf.h
index c478933ee..ce2f5609a 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -23,6 +23,7 @@
 /* Standard ELF types.  */
 
 #include <grub/types.h>
+#include <grub/err.h>
 
 /* Type for a 16-bit quantity.  */
 typedef grub_uint16_t Elf32_Half;
@@ -56,6 +57,9 @@ typedef grub_uint16_t Elf64_Section;
 typedef Elf32_Half Elf32_Versym;
 typedef Elf64_Half Elf64_Versym;
 
+/* Type for number of section header table entries */
+typedef Elf32_Word Elf32_Shnum;
+typedef Elf64_Xword Elf64_Shnum;
 
 /* The ELF file header.  This appears at the start of every ELF file.  */
 
@@ -2531,6 +2535,10 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_RISCV_SET32           56
 #define R_RISCV_32_PCREL        57
 
+extern grub_err_t grub_elf32_get_shnum (Elf32_Ehdr *e, Elf32_Shnum *shnum);
+
+extern grub_err_t grub_elf64_get_shnum (Elf64_Ehdr *e, Elf64_Shnum *shnum);
+
 #ifdef GRUB_TARGET_WORDSIZE
 #if GRUB_TARGET_WORDSIZE == 32
 
@@ -2548,6 +2556,7 @@ typedef Elf32_Sword Elf_Sword;
 typedef Elf32_Sym Elf_Sym;
 typedef Elf32_Word Elf_Word;
 typedef Elf32_Xword Elf_Xword;
+typedef Elf32_Shnum Elf_Shnum;
 
 #define ELF_ST_BIND(val)       ELF32_ST_BIND(val)
 #define ELF_ST_TYPE(val)       ELF32_ST_TYPE(val)
@@ -2557,6 +2566,8 @@ typedef Elf32_Xword Elf_Xword;
 #define ELF_R_TYPE(val)                ELF32_R_TYPE(val)
 #define ELF_R_INFO(sym, type)  ELF32_R_INFO(sym, type)
 
+#define grub_elf_get_shnum     grub_elf32_get_shnum
+
 #elif GRUB_TARGET_WORDSIZE == 64
 
 typedef Elf64_Addr Elf_Addr;
@@ -2573,6 +2584,7 @@ typedef Elf64_Sword Elf_Sword;
 typedef Elf64_Sym Elf_Sym;
 typedef Elf64_Word Elf_Word;
 typedef Elf64_Xword Elf_Xword;
+typedef Elf64_Shnum Elf_Shnum;
 
 #define ELF_ST_BIND(val)       ELF64_ST_BIND (val)
 #define ELF_ST_TYPE(val)       ELF64_ST_TYPE (val)
@@ -2581,6 +2593,8 @@ typedef Elf64_Xword Elf_Xword;
 #define ELF_R_TYPE(val)                ELF64_R_TYPE(val)
 #define ELF_R_INFO(sym, type)  ELF64_R_INFO(sym, type)
 
+#define grub_elf_get_shnum     grub_elf64_get_shnum
+
 #endif /* GRUB_TARGET_WORDSIZE == 64 */
 #endif
 
-- 
2.27.0




reply via email to

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