2005-06-14 Jakub Jelinek * elf.c (bfd_elf_get_str_section): Allocate an extra byte after the end of strtab and clear it. (elf_read): Remove. * elf.c (bfd_section_from_shdr): Fail if name is NULL. Prevent endless recursion on broken objects. * archive.c (do_slurp_coff_armap): Check for overflows. 2005-05-26 Jakub Jelinek * elfcode.h (elf_object_p): Fail if e_shoff != 0, e_shnum == 0 and first shdr has sh_size == 0. Fail if e_shnum is large to cause arithmetic overflow when allocating the i_shdr array. Sanity check sh_link and sh_info fields. Fix e_shstrndx sanity check. 2005-05-18 H.J. Lu * elf.c (group_signature): Check if the symbol table section is correct. 2005-05-17 Tavis Ormandy * elf.c (bfd_section_from_shdr): Add sanity check when parsing dynamic sections. 2005-05-09 Alan Modra * elfcode.h (elf_object_p): Add more sanity checks on elf header. --- bfd/elf.c.jj 2005-02-07 14:42:44.000000000 -0500 +++ bfd/elf.c 2005-06-10 19:22:09.000000000 -0400 @@ -206,28 +206,6 @@ bfd_elf_hash (const char *namearg) return h & 0xffffffff; } -/* Read a specified number of bytes at a specified offset in an ELF - file, into a newly allocated buffer, and return a pointer to the - buffer. */ - -static char * -elf_read (bfd *abfd, file_ptr offset, bfd_size_type size) -{ - char *buf; - - if ((buf = bfd_alloc (abfd, size)) == NULL) - return NULL; - if (bfd_seek (abfd, offset, SEEK_SET) != 0) - return NULL; - if (bfd_bread (buf, size, abfd) != size) - { - if (bfd_get_error () != bfd_error_system_call) - bfd_set_error (bfd_error_file_truncated); - return NULL; - } - return buf; -} - bfd_boolean bfd_elf_mkobject (bfd *abfd) { @@ -267,7 +245,21 @@ bfd_elf_get_str_section (bfd *abfd, unsi /* No cached one, attempt to read, and cache what we read. */ offset = i_shdrp[shindex]->sh_offset; shstrtabsize = i_shdrp[shindex]->sh_size; - shstrtab = elf_read (abfd, offset, shstrtabsize); + + /* Allocate and clear an extra byte at the end, to prevent crashes + in case the string table is not terminated. */ + if (shstrtabsize + 1 == 0 + || (shstrtab = bfd_alloc (abfd, shstrtabsize + 1)) == NULL + || bfd_seek (abfd, offset, SEEK_SET) != 0) + shstrtab = NULL; + else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize) + { + if (bfd_get_error () != bfd_error_system_call) + bfd_set_error (bfd_error_file_truncated); + shstrtab = NULL; + } + else + shstrtab[shstrtabsize] = '\0'; i_shdrp[shindex]->contents = shstrtab; } return shstrtab; @@ -443,8 +435,11 @@ group_signature (bfd *abfd, Elf_Internal Elf_External_Sym_Shndx eshndx; Elf_Internal_Sym isym; - /* First we need to ensure the symbol table is available. */ - if (! bfd_section_from_shdr (abfd, ghdr->sh_link)) + /* First we need to ensure the symbol table is available. Make sure + that it is a symbol table section. */ + hdr = elf_elfsections (abfd) [ghdr->sh_link]; + if (hdr->sh_type != SHT_SYMTAB + || ! bfd_section_from_shdr (abfd, ghdr->sh_link)) return NULL; /* Go read the symbol. */ @@ -1735,6 +1730,8 @@ bfd_section_from_shdr (bfd *abfd, unsign name = bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, hdr->sh_name); + if (name == NULL) + return FALSE; switch (hdr->sh_type) { @@ -1755,6 +1752,9 @@ bfd_section_from_shdr (bfd *abfd, unsign case SHT_DYNAMIC: /* Dynamic linking information. */ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) return FALSE; + if (hdr->sh_link > elf_numsections (abfd) + || elf_elfsections (abfd)[hdr->sh_link] == NULL) + return FALSE; if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB) { Elf_Internal_Shdr *dynsymhdr; @@ -1900,6 +1900,9 @@ bfd_section_from_shdr (bfd *abfd, unsign Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; if (hdr2->sh_link == shindex) { + /* Prevent endless recursion on broken objects. */ + if (i == shindex) + return FALSE; if (! bfd_section_from_shdr (abfd, i)) return FALSE; if (elf_onesymtab (abfd) == i) @@ -1975,6 +1978,10 @@ bfd_section_from_shdr (bfd *abfd, unsign if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF) return _bfd_elf_make_section_from_shdr (abfd, hdr, name); + /* Prevent endless recursion on broken objects. */ + if (elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL + || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA) + return FALSE; if (! bfd_section_from_shdr (abfd, hdr->sh_info)) return FALSE; target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info); --- bfd/elfcode.h.jj 2005-02-07 14:42:44.000000000 -0500 +++ bfd/elfcode.h 2005-05-25 13:09:21.000000000 -0400 @@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suit /* Problems and other issues to resolve. (1) BFD expects there to be some fixed number of "sections" in - the object file. I.E. there is a "section_count" variable in the + the object file. I.E. there is a "section_count" variable in the bfd structure which contains the number of sections. However, ELF supports multiple "views" of a file. In particular, with current implementations, executable files typically have two tables, a @@ -612,8 +612,13 @@ elf_object_p (bfd *abfd) if (i_ehdrp->e_shoff != 0) { + bfd_signed_vma where = i_ehdrp->e_shoff; + + if (where != (file_ptr) where) + goto got_wrong_format_error; + /* Seek to the section header table in the file. */ - if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0) + if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) goto got_no_match; /* Read the first section header at index 0, and convert to internal @@ -625,11 +630,46 @@ elf_object_p (bfd *abfd) /* If the section count is zero, the actual count is in the first section header. */ if (i_ehdrp->e_shnum == SHN_UNDEF) - i_ehdrp->e_shnum = i_shdr.sh_size; + { + i_ehdrp->e_shnum = i_shdr.sh_size; + if (i_ehdrp->e_shnum != i_shdr.sh_size + || i_ehdrp->e_shnum == 0) + goto got_wrong_format_error; + } /* And similarly for the string table index. */ if (i_ehdrp->e_shstrndx == SHN_XINDEX) - i_ehdrp->e_shstrndx = i_shdr.sh_link; + { + i_ehdrp->e_shstrndx = i_shdr.sh_link; + if (i_ehdrp->e_shstrndx != i_shdr.sh_link) + goto got_wrong_format_error; + } + + /* Sanity check that we can read all of the section headers. + It ought to be good enough to just read the last one. */ + if (i_ehdrp->e_shnum != 1) + { + /* Check that we don't have a totally silly number of sections. */ + if (i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (x_shdr) + || i_ehdrp->e_shnum > (unsigned int) -1 / sizeof (i_shdr)) + goto got_wrong_format_error; + + where += (i_ehdrp->e_shnum - 1) * sizeof (x_shdr); + if (where != (file_ptr) where) + goto got_wrong_format_error; + if ((bfd_size_type) where <= i_ehdrp->e_shoff) + goto got_wrong_format_error; + + if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) + goto got_no_match; + if (bfd_bread (&x_shdr, sizeof x_shdr, abfd) != sizeof (x_shdr)) + goto got_no_match; + + /* Back to where we were. */ + where = i_ehdrp->e_shoff + sizeof (x_shdr); + if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0) + goto got_no_match; + } } /* Allocate space for a copy of the section header table in @@ -673,6 +713,20 @@ elf_object_p (bfd *abfd) goto got_no_match; elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); + /* Sanity check sh_link and sh_info. */ + if (i_shdrp[shindex].sh_link >= num_sec + || (i_shdrp[shindex].sh_link >= SHN_LORESERVE + && i_shdrp[shindex].sh_link <= SHN_HIRESERVE)) + goto got_wrong_format_error; + + if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK) + || i_shdrp[shindex].sh_type == SHT_RELA + || i_shdrp[shindex].sh_type == SHT_REL) + && (i_shdrp[shindex].sh_info >= num_sec + || (i_shdrp[shindex].sh_info >= SHN_LORESERVE + && i_shdrp[shindex].sh_info <= SHN_HIRESERVE))) + goto got_wrong_format_error; + /* If the section is loaded, but not page aligned, clear D_PAGED. */ if (i_shdrp[shindex].sh_size != 0 @@ -685,6 +739,17 @@ elf_object_p (bfd *abfd) } } + /* A further sanity check. */ + if (i_ehdrp->e_shnum != 0) + { + if (i_ehdrp->e_shstrndx >= elf_numsections (abfd) + || (i_ehdrp->e_shstrndx >= SHN_LORESERVE + && i_ehdrp->e_shstrndx <= SHN_HIRESERVE)) + goto got_wrong_format_error; + } + else if (i_ehdrp->e_shstrndx != 0) + goto got_wrong_format_error; + /* Read in the program headers. */ if (i_ehdrp->e_phnum == 0) elf_tdata (abfd)->phdr = NULL; @@ -1042,7 +1107,7 @@ elf_slurp_symbol_table (bfd *abfd, asymb symcount); /* Slurp in the symbols without the version information, - since that is more helpful than just quitting. */ + since that is more helpful than just quitting. */ verhdr = NULL; } @@ -1107,7 +1172,7 @@ elf_slurp_symbol_table (bfd *abfd, asymb sym->symbol.section = bfd_abs_section_ptr; /* If this is a relocatable file, then the symbol value is - already section relative. */ + already section relative. */ if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) sym->symbol.value -= sym->symbol.section->vma; --- bfd/archive.c.jj 2005-06-10 19:02:01.000000000 +0200 +++ bfd/archive.c 2005-06-10 19:50:21.000000000 +0200 @@ -821,9 +821,15 @@ do_slurp_coff_armap (bfd *abfd) /* The coff armap must be read sequentially. So we construct a bsd-style one in core all at once, for simplicity. */ + if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym)) + return FALSE; + carsym_size = (nsymz * sizeof (carsym)); ptrsize = (4 * nsymz); + if (carsym_size + stringsize + 1 <= carsym_size) + return FALSE; + ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1); if (ardata->symdefs == NULL) return FALSE;