diff options
author | emaste <emaste@FreeBSD.org> | 2017-05-03 01:57:06 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2017-05-03 01:57:06 +0000 |
commit | f7c08dd2f80cc8ae2724991b203c31fb1335db67 (patch) | |
tree | 4c945b710b7f339c145fd35cd67f26e6ec425bff | |
parent | 47c37b9abcd0bf1a8e5b85df65382d1d214fc577 (diff) | |
download | FreeBSD-src-f7c08dd2f80cc8ae2724991b203c31fb1335db67.zip FreeBSD-src-f7c08dd2f80cc8ae2724991b203c31fb1335db67.tar.gz |
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.)
-rw-r--r-- | contrib/elftoolchain/libelf/gelf_phdr.c | 32 | ||||
-rw-r--r-- | contrib/elftoolchain/libelf/libelf_ehdr.c | 17 |
2 files changed, 23 insertions, 26 deletions
diff --git a/contrib/elftoolchain/libelf/gelf_phdr.c b/contrib/elftoolchain/libelf/gelf_phdr.c index 31e20b0..4786b27 100644 --- a/contrib/elftoolchain/libelf/gelf_phdr.c +++ b/contrib/elftoolchain/libelf/gelf_phdr.c @@ -53,10 +53,17 @@ gelf_getphdr(Elf *e, int index, GElf_Phdr *d) 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_Phdr *d) ((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_Phdr *d) (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_Phdr *s) 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); } diff --git a/contrib/elftoolchain/libelf/libelf_ehdr.c b/contrib/elftoolchain/libelf/libelf_ehdr.c index d375fb3..08c4a17 100644 --- a/contrib/elftoolchain/libelf/libelf_ehdr.c +++ b/contrib/elftoolchain/libelf/libelf_ehdr.c @@ -170,10 +170,6 @@ _libelf_ehdr(Elf *e, int ec, int allocate) (*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 allocate) 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); } |