Author: emaste
Date: Wed May  3 01:57:06 2017
New Revision: 317716
URL: https://svnweb.freebsd.org/changeset/base/317716

Log:
  MFC libelf: Fix extended numbering
  
  r310136 (cem): libelf: Fix extended numbering detection
  
  Extended numbering is used for any of these fields overflowing.
  
  r310137 (cem): gelf_getphdr: Allow extended indices
  
  Needed for 'readelf -l' of extended phnum files.  (Parity with GNU
  binutils.)

Modified:
  stable/11/contrib/elftoolchain/libelf/gelf_phdr.c
  stable/11/contrib/elftoolchain/libelf/libelf_ehdr.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/contrib/elftoolchain/libelf/gelf_phdr.c
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/gelf_phdr.c   Wed May  3 01:46:39 
2017        (r317715)
+++ stable/11/contrib/elftoolchain/libelf/gelf_phdr.c   Wed May  3 01:57:06 
2017        (r317716)
@@ -53,10 +53,17 @@ gelf_getphdr(Elf *e, int index, GElf_Phd
        Elf64_Ehdr *eh64;
        Elf32_Phdr *ep32;
        Elf64_Phdr *ep64;
+       size_t phnum;
 
        if (d == NULL || e == NULL ||
            ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
-           (e->e_kind != ELF_K_ELF) || index < 0) {
+           (e->e_kind != ELF_K_ELF) || index < 0 ||
+           elf_getphdrnum(e, &phnum) < 0) {
+               LIBELF_SET_ERROR(ARGUMENT, 0);
+               return (NULL);
+       }
+
+       if ((size_t)index >= phnum) {
                LIBELF_SET_ERROR(ARGUMENT, 0);
                return (NULL);
        }
@@ -66,11 +73,6 @@ gelf_getphdr(Elf *e, int index, GElf_Phd
                    ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL))
                        return (NULL);
 
-               if (index >= eh32->e_phnum) {
-                       LIBELF_SET_ERROR(ARGUMENT, 0);
-                       return (NULL);
-               }
-
                ep32 += index;
 
                d->p_type   = ep32->p_type;
@@ -87,11 +89,6 @@ gelf_getphdr(Elf *e, int index, GElf_Phd
                    (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL)
                        return (NULL);
 
-               if (index >= eh64->e_phnum) {
-                       LIBELF_SET_ERROR(ARGUMENT, 0);
-                       return (NULL);
-               }
-
                ep64 += index;
 
                *d = *ep64;
@@ -125,13 +122,15 @@ gelf_newphdr(Elf *e, size_t count)
 int
 gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s)
 {
-       int ec, phnum;
+       int ec;
+       size_t phnum;
        void *ehdr;
        Elf32_Phdr *ph32;
        Elf64_Phdr *ph64;
 
        if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF ||
-           ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
+           ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
+           elf_getphdrnum(e, &phnum) < 0) {
                LIBELF_SET_ERROR(ARGUMENT, 0);
                return (0);
        }
@@ -144,12 +143,7 @@ gelf_update_phdr(Elf *e, int ndx, GElf_P
        if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
                return (0);
 
-       if (ec == ELFCLASS32)
-               phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
-       else
-               phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
-
-       if (ndx < 0 || ndx > phnum) {
+       if (ndx < 0 || (size_t)ndx > phnum) {
                LIBELF_SET_ERROR(ARGUMENT, 0);
                return (0);
        }

Modified: stable/11/contrib/elftoolchain/libelf/libelf_ehdr.c
==============================================================================
--- stable/11/contrib/elftoolchain/libelf/libelf_ehdr.c Wed May  3 01:46:39 
2017        (r317715)
+++ stable/11/contrib/elftoolchain/libelf/libelf_ehdr.c Wed May  3 01:57:06 
2017        (r317716)
@@ -170,10 +170,6 @@ _libelf_ehdr(Elf *e, int ec, int allocat
        (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
            e->e_byteorder != LIBELF_PRIVATE(byteorder));
 
-       /*
-        * If extended numbering is being used, read the correct
-        * number of sections and program header entries.
-        */
        if (ec == ELFCLASS32) {
                phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
                shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
@@ -193,12 +189,19 @@ _libelf_ehdr(Elf *e, int ec, int allocat
                return (NULL);
        }
 
-       if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */
+       /*
+        * If extended numbering is being used, read the correct
+        * number of sections and program header entries.
+        */
+       if ((shnum == 0 && shoff != 0) || phnum == PN_XNUM || strndx == 
SHN_XINDEX) {
+               if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
+                       return (NULL);
+       } else {
+               /* not using extended numbering */
                e->e_u.e_elf.e_nphdr = phnum;
                e->e_u.e_elf.e_nscn = shnum;
                e->e_u.e_elf.e_strndx = strndx;
-       } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
-               return (NULL);
+       }
 
        return (ehdr);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to