From: Mark Wielaard Date: Sun, 16 Nov 2014 23:33:36 +0000 (+0100) Subject: libelf: Fix handling of (extended) phnum. X-Git-Tag: elfutils-0.161~83 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=436275edd015ab6a6f8e164ee2292f74f03d2413;p=thirdparty%2Felfutils.git 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 --- diff --git a/libelf/ChangeLog b/libelf/ChangeLog index beb431fda..ef5da43d4 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,10 @@ +2014-11-16 Mark Wielaard + + * 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 * gelf_getnote.c (gelf_getnote): Check padding overflow. diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c index e74e63fd5..1b82a4802 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 99649beef..d8e34d7e5 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 fefd6c1d9..737c67435 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2014-11-16 Mark Wielaard + + * 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 * readelf.c (print_cfa_program): Check block len before calling diff --git a/src/readelf.c b/src/readelf.c index 697a0e507..583b5daf6 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;