| From bdc5166c274b842f83f8328e7cfaaf80fd29934e Mon Sep 17 00:00:00 2001 |
| From: Nick Clifton <nickc@redhat.com> |
| Date: Mon, 13 Feb 2017 13:08:32 +0000 |
| Subject: [PATCH 1/2] Fix readelf writing to illegal addresses whilst |
| processing corrupt input files containing symbol-difference relocations. |
| |
| PR binutils/21137 |
| * readelf.c (target_specific_reloc_handling): Add end parameter. |
| Check for buffer overflow before writing relocated values. |
| (apply_relocations): Pass end to target_specific_reloc_handling. |
| |
| (cherry pick from commit 03f7786e2f440b9892b1c34a58fb26222ce1b493) |
| Upstream-Status: Backport [master] |
| CVE: CVE-2017-6965 |
| |
| Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com> |
| --- |
| binutils/ChangeLog | 7 +++++++ |
| binutils/readelf.c | 30 +++++++++++++++++++++++++----- |
| 2 files changed, 32 insertions(+), 5 deletions(-) |
| |
| diff --git a/binutils/ChangeLog b/binutils/ChangeLog |
| index f21867f98c..e789a3b99b 100644 |
| --- a/binutils/ChangeLog |
| +++ b/binutils/ChangeLog |
| @@ -1,3 +1,10 @@ |
| +2017-02-13 Nick Clifton <nickc@redhat.com> |
| + |
| + PR binutils/21137 |
| + * readelf.c (target_specific_reloc_handling): Add end parameter. |
| + Check for buffer overflow before writing relocated values. |
| + (apply_relocations): Pass end to target_specific_reloc_handling. |
| + |
| 2017-03-02 Tristan Gingold <gingold@adacore.com> |
| |
| * configure: Regenerate. |
| diff --git a/binutils/readelf.c b/binutils/readelf.c |
| index b5f577f5a1..8cdaae3b8c 100644 |
| --- a/binutils/readelf.c |
| +++ b/binutils/readelf.c |
| @@ -11585,6 +11585,7 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED) |
| static bfd_boolean |
| target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| unsigned char * start, |
| + unsigned char * end, |
| Elf_Internal_Sym * symtab) |
| { |
| unsigned int reloc_type = get_reloc_type (reloc->r_info); |
| @@ -11625,13 +11626,19 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| handle_sym_diff: |
| if (saved_sym != NULL) |
| { |
| + int reloc_size = reloc_type == 1 ? 4 : 2; |
| bfd_vma value; |
| |
| value = reloc->r_addend |
| + (symtab[get_reloc_symindex (reloc->r_info)].st_value |
| - saved_sym->st_value); |
| |
| - byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2); |
| + if (start + reloc->r_offset + reloc_size >= end) |
| + /* PR 21137 */ |
| + error (_("MSP430 sym diff reloc writes past end of section (%p vs %p)\n"), |
| + start + reloc->r_offset + reloc_size, end); |
| + else |
| + byte_put (start + reloc->r_offset, value, reloc_size); |
| |
| saved_sym = NULL; |
| return TRUE; |
| @@ -11662,13 +11669,18 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| case 2: /* R_MN10300_16 */ |
| if (saved_sym != NULL) |
| { |
| + int reloc_size = reloc_type == 1 ? 4 : 2; |
| bfd_vma value; |
| |
| value = reloc->r_addend |
| + (symtab[get_reloc_symindex (reloc->r_info)].st_value |
| - saved_sym->st_value); |
| |
| - byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2); |
| + if (start + reloc->r_offset + reloc_size >= end) |
| + error (_("MN10300 sym diff reloc writes past end of section (%p vs %p)\n"), |
| + start + reloc->r_offset + reloc_size, end); |
| + else |
| + byte_put (start + reloc->r_offset, value, reloc_size); |
| |
| saved_sym = NULL; |
| return TRUE; |
| @@ -11703,12 +11715,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| break; |
| |
| case 0x41: /* R_RL78_ABS32. */ |
| - byte_put (start + reloc->r_offset, value, 4); |
| + if (start + reloc->r_offset + 4 >= end) |
| + error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"), |
| + start + reloc->r_offset + 2, end); |
| + else |
| + byte_put (start + reloc->r_offset, value, 4); |
| value = 0; |
| return TRUE; |
| |
| case 0x43: /* R_RL78_ABS16. */ |
| - byte_put (start + reloc->r_offset, value, 2); |
| + if (start + reloc->r_offset + 2 >= end) |
| + error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"), |
| + start + reloc->r_offset + 2, end); |
| + else |
| + byte_put (start + reloc->r_offset, value, 2); |
| value = 0; |
| return TRUE; |
| |
| @@ -12325,7 +12345,7 @@ apply_relocations (void * file, |
| |
| reloc_type = get_reloc_type (rp->r_info); |
| |
| - if (target_specific_reloc_handling (rp, start, symtab)) |
| + if (target_specific_reloc_handling (rp, start, end, symtab)) |
| continue; |
| else if (is_none_reloc (reloc_type)) |
| continue; |
| -- |
| 2.11.0 |
| |