$NetBSD: patch-bo,v 1.1 2007/07/03 12:32:28 lkundrak Exp $ Patch for CVE-2005-1704 sucked from upstream. * elfcode.h (elf_object_p): Add more sanity checks on elf header. --- bfd/elfcode.h.orig 2004-06-24 06:46:22.000000000 +0200 +++ bfd/elfcode.h @@ -613,8 +613,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 @@ -626,13 +631,50 @@ 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) + 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)) + 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; + } } + /* A further sanity check. */ + if (i_ehdrp->e_shstrndx >= i_ehdrp->e_shnum) + goto got_wrong_format_error; + /* Allocate space for a copy of the section header table in internal form. */ if (i_ehdrp->e_shnum != 0)