Subject: Limit the number of program and section header number of sections to be (...) ID: CVE-2014-8116 Upstream-Author: Christos Zoulas Date: Sat Nov 22 16:04:29 2014 +0000 Origin: FILE5_20-27-gb4c0114 Last-Update: 2015-01-09 - limit the number of program and section header number of sections to be processed to avoid excessive processing time. - if a bad note is found, return 0 to stop processing immediately. --- a/src/elfclass.h +++ b/src/elfclass.h @@ -35,9 +35,11 @@ switch (type) { #ifdef ELFCORE case ET_CORE: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); if (dophn_core(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), fsize, &flags) == -1) return -1; @@ -45,18 +47,24 @@ #endif case ET_EXEC: case ET_DYN: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (dophn_exec(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), - fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) - == -1) + fsize, &flags, shnum) == -1) return -1; /*FALLTHROUGH*/ case ET_REL: + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (doshn(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_shoff), - elf_getu16(swap, elfhdr.e_shnum), + (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, (size_t)elf_getu16(swap, elfhdr.e_shentsize), &flags, elf_getu16(swap, elfhdr.e_machine)) == -1) --- a/src/readelf.c +++ b/src/readelf.c @@ -60,6 +60,18 @@ private uint32_t getu32(int, uint32_t); private uint64_t getu64(int, uint64_t); +#define MAX_PHNUM 256 +#define MAX_SHNUM 1024 + +private int +toomany(struct magic_set *ms, const char *name, uint16_t num) +{ + if (file_printf(ms, ", too many %s header sections (%u)", name, num + ) == -1) + return -1; + return 0; +} + private uint16_t getu16(int swap, uint16_t value) { @@ -398,13 +410,13 @@ if (namesz & 0x80000000) { (void)file_printf(ms, ", bad note name size 0x%lx", (unsigned long)namesz); - return offset; + return 0; } if (descsz & 0x80000000) { (void)file_printf(ms, ", bad note description size 0x%lx", (unsigned long)descsz); - return offset; + return 0; } @@ -1165,7 +1177,7 @@ int flags = 0; Elf32_Ehdr elf32hdr; Elf64_Ehdr elf64hdr; - uint16_t type; + uint16_t type, phnum, shnum; if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) return 0;