commit a941291cab71b9ac356e1c03968c177c03e602ab Author: Alan Modra Date: Sat Apr 29 14:48:16 2017 +0930 PR21432, buffer overflow in perform_relocation The existing reloc offset range tests didn't catch small negative offsets less than the size of the reloc field. PR 21432 * reloc.c (reloc_offset_in_range): New function. (bfd_perform_relocation, bfd_install_relocation): Use it. (_bfd_final_link_relocate): Likewise. Upstream-Status: Backport CVE: CVE-2017-8396 Signed-off-by: Thiruvadi Rajaraman Index: git/bfd/reloc.c =================================================================== --- git.orig/bfd/reloc.c 2017-09-05 18:12:07.448886623 +0530 +++ git/bfd/reloc.c 2017-09-05 18:12:07.564887511 +0530 @@ -538,6 +538,22 @@ return flag; } +/* HOWTO describes a relocation, at offset OCTET. Return whether the + relocation field is within SECTION of ABFD. */ + +static bfd_boolean +reloc_offset_in_range (reloc_howto_type *howto, bfd *abfd, + asection *section, bfd_size_type octet) +{ + bfd_size_type octet_end = bfd_get_section_limit_octets (abfd, section); + bfd_size_type reloc_size = bfd_get_reloc_size (howto); + + /* The reloc field must be contained entirely within the section. + Allow zero length fields (marker relocs or NONE relocs where no + relocation will be performed) at the end of the section. */ + return octet <= octet_end && octet + reloc_size <= octet_end; +} + /* FUNCTION bfd_perform_relocation @@ -618,15 +634,9 @@ return cont; } - /* Is the address of the relocation really within the section? - Include the size of the reloc in the test for out of range addresses. - PR 17512: file: c146ab8b, 46dff27f, 38e53ebf. */ + /* Is the address of the relocation really within the section? */ octets = reloc_entry->address * bfd_octets_per_byte (abfd); - if (octets + bfd_get_reloc_size (howto) - > bfd_get_section_limit_octets (abfd, input_section) - /* Check for an overly large offset which - masquerades as a negative value too. */ - || (octets + bfd_get_reloc_size (howto) < bfd_get_reloc_size (howto))) + if (!reloc_offset_in_range (howto, abfd, input_section, octets)) return bfd_reloc_outofrange; /* Work out which section the relocation is targeted at and the @@ -1010,8 +1020,7 @@ /* Is the address of the relocation really within the section? */ octets = reloc_entry->address * bfd_octets_per_byte (abfd); - if (octets + bfd_get_reloc_size (howto) - > bfd_get_section_limit_octets (abfd, input_section)) + if (!reloc_offset_in_range (howto, abfd, input_section, octets)) return bfd_reloc_outofrange; /* Work out which section the relocation is targeted at and the @@ -1349,8 +1358,7 @@ bfd_size_type octets = address * bfd_octets_per_byte (input_bfd); /* Sanity check the address. */ - if (octets + bfd_get_reloc_size (howto) - > bfd_get_section_limit_octets (input_bfd, input_section)) + if (!reloc_offset_in_range (howto, input_bfd, input_section, octets)) return bfd_reloc_outofrange; /* This function assumes that we are dealing with a basic relocation Index: git/bfd/ChangeLog =================================================================== --- git.orig/bfd/ChangeLog 2017-09-05 18:12:07.448886623 +0530 +++ git/bfd/ChangeLog 2017-09-05 18:13:46.745645897 +0530 @@ -73,6 +73,13 @@ (evax_bfd_print_egsd): Check for an overlarge record length. (evax_bfd_print_etir): Likewise. +2017-04-29 Alan Modra + + PR 21432 + * reloc.c (reloc_offset_in_range): New function. + (bfd_perform_relocation, bfd_install_relocation): Use it. + (_bfd_final_link_relocate): Likewise. + 2017-04-26 Nick Clifton PR binutils/21434