From: Roland McGrath Date: Fri, 8 Jan 2010 03:51:42 +0000 (-0800) Subject: Merge branch 'master' into robustify X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=133458b3727dcbb024ba5a3139b5a14eccb10e3b;p=thirdparty%2Felfutils.git Merge branch 'master' into robustify Conflicts: libelf/elf32_getphdr.c libelf/elf_begin.c --- 133458b3727dcbb024ba5a3139b5a14eccb10e3b diff --cc libelf/elf32_newphdr.c index 589322294,03ff100a5..9191d4418 --- a/libelf/elf32_newphdr.c +++ b/libelf/elf32_newphdr.c @@@ -122,14 -132,9 +132,15 @@@ elfw2(LIBELFBITS,newphdr) (elf, count result = NULL; } else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count + || count == PN_XNUM || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) { + if (unlikely (count > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr)))) + { + result = NULL; + goto out; + } + /* Allocate a new program header with the appropriate number of elements. */ result = (ElfW2(LIBELFBITS,Phdr) *) diff --cc libelf/elf_begin.c index 4c1b1b8e8,896d86b69..57b36afa5 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@@ -287,18 -285,12 +287,21 @@@ file_read_elf (int fildes, void *map_ad /* Could not determine the number of sections. */ return NULL; + /* Check for too many sections. */ + if (e_ident[EI_CLASS] == ELFCLASS32) + { + if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr))) + return NULL; + } + else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr))) + return NULL; + - /* We can now allocate the memory. */ + /* We can now allocate the memory. Even if there are no section headers, + we allocate space for a zeroth section in case we need it later. */ + const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP) + ? 1 : 0); Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent, - ELF_K_ELF, scncnt * sizeof (Elf_Scn)); + ELF_K_ELF, scnmax * sizeof (Elf_Scn)); if (elf == NULL) /* Not enough memory. */ return NULL; @@@ -329,30 -324,13 +335,33 @@@ { /* We can use the mmapped memory. */ elf->state.elf32.ehdr = ehdr; + + if (unlikely (ehdr->e_shoff >= maxsize) + || unlikely (maxsize - ehdr->e_shoff + < scncnt * sizeof (Elf32_Shdr))) + { + free_and_out: + free (elf); + __libelf_seterrno (ELF_E_INVALID_FILE); + return NULL; + } elf->state.elf32.shdr = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); - if (ehdr->e_phnum > 0) - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ - elf->state.elf32.phdr - = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); + - if (ehdr->e_phnum > 0) ++ size_t phnum = ehdr->e_phnum; ++ if (phnum == PN_XNUM && scncnt > 0) ++ phnum = elf->state.elf32.shdr[0].sh_info; ++ if (phnum > 0) + { - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ ++ /* Assign a value only if there really is a program ++ header. Otherwise the value remains NULL. */ + if (unlikely (ehdr->e_phoff >= maxsize) + || unlikely (maxsize - ehdr->e_phoff - < ehdr->e_phnum * sizeof (Elf32_Phdr))) ++ < phnum * sizeof (Elf32_Phdr))) + goto free_and_out; - elf->state.elf32.phdr - = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); ++ elf->state.elf32.phdr ++ = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff); + } for (size_t cnt = 0; cnt < scncnt; ++cnt) { @@@ -434,26 -409,13 +440,28 @@@ { /* We can use the mmapped memory. */ elf->state.elf64.ehdr = ehdr; + + if (unlikely (ehdr->e_shoff >= maxsize) + || unlikely (ehdr->e_shoff + + scncnt * sizeof (Elf32_Shdr) > maxsize)) + goto free_and_out; elf->state.elf64.shdr = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff); - if (ehdr->e_phnum > 0) - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ - elf->state.elf64.phdr - = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff); + - if (ehdr->e_phnum > 0) ++ size_t phnum = ehdr->e_phnum; ++ if (phnum == PN_XNUM && scncnt > 0) ++ phnum = elf->state.elf64.shdr[0].sh_info; ++ if (phnum > 0) + { - /* Assign a value only if there really is a program - header. Otherwise the value remains NULL. */ ++ /* Assign a value only if there really is a program ++ header. Otherwise the value remains NULL. */ + if (unlikely (ehdr->e_phoff >= maxsize) + || unlikely (ehdr->e_phoff - + ehdr->e_phnum - * sizeof (Elf32_Phdr) > maxsize)) ++ + phnum * sizeof (Elf32_Phdr) > maxsize)) + goto free_and_out; - elf->state.elf64.phdr - = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff); ++ elf->state.elf64.phdr ++ = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff); + } for (size_t cnt = 0; cnt < scncnt; ++cnt) {