diff options
| author | Mark Wielaard <[email protected]> | 2014-11-17 00:33:36 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2014-11-17 00:33:36 +0100 |
| commit | 436275edd015ab6a6f8e164ee2292f74f03d2413 (patch) | |
| tree | 3ae7d3d504f409719f7e3194b5121cfc1ccc8c32 | |
| parent | 2af7b4942ad1e08d6e0609afec4edc82588f089e (diff) | |
libelf: Fix handling of (extended) phnum.
If there is no e_phoff e_phnum cannot be trusted. Extended phnum can only
be gotten if we have an actual section table and a shdr for section zero,
Extended phnum can be too large to fit in the file (or a size_t).
Signed-off-by: Mark Wielaard <[email protected]>
| -rw-r--r-- | libelf/ChangeLog | 7 | ||||
| -rw-r--r-- | libelf/elf32_getphdr.c | 6 | ||||
| -rw-r--r-- | libelf/elf_getphdrnum.c | 18 | ||||
| -rw-r--r-- | src/ChangeLog | 6 | ||||
| -rw-r--r-- | src/readelf.c | 7 |
5 files changed, 36 insertions, 8 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index beb431fd..ef5da43d 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,5 +1,12 @@ 2014-11-16 Mark Wielaard <[email protected]> + * elf32_getphdr.c (getphdr_wrlock): Check e_phoff isn't zero. + Check for too many pheaders. + * elf_getphdrnum.c (__elf_getphdrnum_rdlock): Check section zero + actually exists before handling PN_XNUM. + +2014-11-16 Mark Wielaard <[email protected]> + * gelf_getnote.c (gelf_getnote): Check padding overflow. 2014-11-16 Mark Wielaard <[email protected]> diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c index e74e63fd..1b82a480 100644 --- a/libelf/elf32_getphdr.c +++ b/libelf/elf32_getphdr.c @@ -76,15 +76,17 @@ __elfw2(LIBELFBITS,getphdr_wrlock) (elf) size_t phnum; if (__elf_getphdrnum_rdlock (elf, &phnum) != 0) goto out; - if (phnum == 0) + if (phnum == 0 || ehdr->e_phoff == 0) { __libelf_seterrno (ELF_E_NO_PHDR); goto out; } + /* Check this doesn't overflow. */ size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr)); - if (ehdr->e_phoff > elf->maximum_size + if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr)) + || ehdr->e_phoff > elf->maximum_size || elf->maximum_size - ehdr->e_phoff < size) { __libelf_seterrno (ELF_E_INVALID_DATA); diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c index 99649bee..d8e34d7e 100644 --- a/libelf/elf_getphdrnum.c +++ b/libelf/elf_getphdrnum.c @@ -1,5 +1,5 @@ /* Return number of program headers in the ELF file. - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010, 2014 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -62,10 +62,18 @@ __elf_getphdrnum_rdlock (elf, dst) /* If there are no section headers, perhaps this is really just 65536 written without PN_XNUM support. Either that or it's bad data. */ - if (likely (scns->cnt > 0)) - *dst = (elf->class == ELFCLASS32 - ? scns->data[0].shdr.e32->sh_info - : scns->data[0].shdr.e64->sh_info); + if (elf->class == ELFCLASS32) + { + if (likely (scns->cnt > 0 + && elf->state.elf32.scns.data[0].shdr.e32 != NULL)) + *dst = scns->data[0].shdr.e32->sh_info; + } + else + { + if (likely (scns->cnt > 0 + && elf->state.elf64.scns.data[0].shdr.e64 != NULL)) + *dst = scns->data[0].shdr.e64->sh_info; + } } return 0; diff --git a/src/ChangeLog b/src/ChangeLog index fefd6c1d..737c6743 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,11 @@ 2014-11-16 Mark Wielaard <[email protected]> + * readelf (process_elf_file): Set phnum to zero if there aren't + actually any pheaders. + (print_phdr): Check there actually is a phdr. + +2014-11-16 Mark Wielaard <[email protected]> + * readelf.c (print_cfa_program): Check block len before calling print_ops. diff --git a/src/readelf.c b/src/readelf.c index 697a0e50..583b5daf 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -835,6 +835,11 @@ process_elf_file (Dwfl_Module *dwflmod, int fd) gettext ("cannot determine number of program headers: %s"), elf_errmsg (-1)); + /* If there isn't actually a program header then set phnum to zero. + Don't do any extra work. gelf_getphdr will always return NULL. */ + if (ehdr->e_phoff == 0) + phnum = 0; + /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and may have applied relocation to some sections. So we need to get a fresh Elf handle on the file to display those. */ @@ -1157,7 +1162,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\ static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) { - if (ehdr->e_phnum == 0) + if (ehdr->e_phnum == 0 || ehdr->e_phoff == 0) /* No program header, this is OK in relocatable objects. */ return; |
