| From a941291cab71b9ac356e1c03968c177c03e602ab Mon Sep 17 00:00:00 2001 |
| From: Alan Modra <amodra@gmail.com> |
| Date: Sat, 29 Apr 2017 14:48:16 +0930 |
| Subject: [PATCH] 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 |
| CVE: CVE-2017-8397 |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| bfd/ChangeLog | 7 +++++++ |
| bfd/reloc.c | 32 ++++++++++++++++++++------------ |
| 2 files changed, 27 insertions(+), 12 deletions(-) |
| |
| Index: git/bfd/reloc.c |
| =================================================================== |
| --- git.orig/bfd/reloc.c |
| +++ git/bfd/reloc.c |
| @@ -538,6 +538,22 @@ bfd_check_overflow (enum complain_overfl |
| 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,13 +634,10 @@ bfd_perform_relocation (bfd *abfd, |
| /* PR 17512: file: 0f67f69d. */ |
| if (howto == NULL) |
| return bfd_reloc_undefined; |
| - |
| - /* 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)) |
| + 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 |
| @@ -1012,8 +1025,7 @@ bfd_install_relocation (bfd *abfd, |
| |
| /* 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 |
| @@ -1351,8 +1363,7 @@ _bfd_final_link_relocate (reloc_howto_ty |
| 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 |
| +++ git/bfd/ChangeLog |
| @@ -1,3 +1,10 @@ |
| +2017-04-29 Alan Modra <amodra@gmail.com> |
| + |
| + 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 <nickc@redhat.com> |
| |
| PR binutils/21431 |