Brad Bishop | 37a0e4d | 2017-12-04 01:01:44 -0500 | [diff] [blame^] | 1 | From 6f898c17b1d6f6a29a05ca6de31f0fc8f52cfbfe Mon Sep 17 00:00:00 2001 |
| 2 | From: Nick Clifton <nickc@redhat.com> |
| 3 | Date: Mon, 13 Feb 2017 13:08:32 +0000 |
| 4 | Subject: [PATCH 1/2] Fix readelf writing to illegal addresses whilst |
| 5 | processing corrupt input files containing symbol-difference relocations. |
| 6 | |
| 7 | PR binutils/21137 |
| 8 | * readelf.c (target_specific_reloc_handling): Add end parameter. |
| 9 | Check for buffer overflow before writing relocated values. |
| 10 | (apply_relocations): Pass end to target_specific_reloc_handling. |
| 11 | |
| 12 | (cherry pick from commit 03f7786e2f440b9892b1c34a58fb26222ce1b493) |
| 13 | Upstream-Status: Backport [master] |
| 14 | CVE: CVE-2017-6965 |
| 15 | |
| 16 | Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com> |
| 17 | --- |
| 18 | binutils/ChangeLog | 7 +++++++ |
| 19 | binutils/readelf.c | 30 +++++++++++++++++++++++++----- |
| 20 | 2 files changed, 32 insertions(+), 5 deletions(-) |
| 21 | |
| 22 | diff --git a/binutils/ChangeLog b/binutils/ChangeLog |
| 23 | index 995de87dc3..154b797a29 100644 |
| 24 | --- a/binutils/ChangeLog |
| 25 | +++ b/binutils/ChangeLog |
| 26 | @@ -5,6 +5,13 @@ |
| 27 | Check for buffer overflow before writing relocated values. |
| 28 | (apply_relocations): Pass end to target_specific_reloc_handling. |
| 29 | |
| 30 | +2017-02-13 Nick Clifton <nickc@redhat.com> |
| 31 | + |
| 32 | + PR binutils/21137 |
| 33 | + * readelf.c (target_specific_reloc_handling): Add end parameter. |
| 34 | + Check for buffer overflow before writing relocated values. |
| 35 | + (apply_relocations): Pass end to target_specific_reloc_handling. |
| 36 | + |
| 37 | 2016-08-03 Tristan Gingold <gingold@adacore.com> |
| 38 | |
| 39 | * configure: Regenerate. |
| 40 | diff --git a/binutils/readelf.c b/binutils/readelf.c |
| 41 | index d31558c3b4..220671f76f 100644 |
| 42 | --- a/binutils/readelf.c |
| 43 | +++ b/binutils/readelf.c |
| 44 | @@ -11345,6 +11345,7 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED) |
| 45 | static bfd_boolean |
| 46 | target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| 47 | unsigned char * start, |
| 48 | + unsigned char * end, |
| 49 | Elf_Internal_Sym * symtab) |
| 50 | { |
| 51 | unsigned int reloc_type = get_reloc_type (reloc->r_info); |
| 52 | @@ -11384,13 +11385,19 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| 53 | handle_sym_diff: |
| 54 | if (saved_sym != NULL) |
| 55 | { |
| 56 | + int reloc_size = reloc_type == 1 ? 4 : 2; |
| 57 | bfd_vma value; |
| 58 | |
| 59 | value = reloc->r_addend |
| 60 | + (symtab[get_reloc_symindex (reloc->r_info)].st_value |
| 61 | - saved_sym->st_value); |
| 62 | |
| 63 | - byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2); |
| 64 | + if (start + reloc->r_offset + reloc_size >= end) |
| 65 | + /* PR 21137 */ |
| 66 | + error (_("MSP430 sym diff reloc writes past end of section (%p vs %p)\n"), |
| 67 | + start + reloc->r_offset + reloc_size, end); |
| 68 | + else |
| 69 | + byte_put (start + reloc->r_offset, value, reloc_size); |
| 70 | |
| 71 | saved_sym = NULL; |
| 72 | return TRUE; |
| 73 | @@ -11421,13 +11428,18 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| 74 | case 2: /* R_MN10300_16 */ |
| 75 | if (saved_sym != NULL) |
| 76 | { |
| 77 | + int reloc_size = reloc_type == 1 ? 4 : 2; |
| 78 | bfd_vma value; |
| 79 | |
| 80 | value = reloc->r_addend |
| 81 | + (symtab[get_reloc_symindex (reloc->r_info)].st_value |
| 82 | - saved_sym->st_value); |
| 83 | |
| 84 | - byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2); |
| 85 | + if (start + reloc->r_offset + reloc_size >= end) |
| 86 | + error (_("MN10300 sym diff reloc writes past end of section (%p vs %p)\n"), |
| 87 | + start + reloc->r_offset + reloc_size, end); |
| 88 | + else |
| 89 | + byte_put (start + reloc->r_offset, value, reloc_size); |
| 90 | |
| 91 | saved_sym = NULL; |
| 92 | return TRUE; |
| 93 | @@ -11462,12 +11474,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, |
| 94 | break; |
| 95 | |
| 96 | case 0x41: /* R_RL78_ABS32. */ |
| 97 | - byte_put (start + reloc->r_offset, value, 4); |
| 98 | + if (start + reloc->r_offset + 4 >= end) |
| 99 | + error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"), |
| 100 | + start + reloc->r_offset + 2, end); |
| 101 | + else |
| 102 | + byte_put (start + reloc->r_offset, value, 4); |
| 103 | value = 0; |
| 104 | return TRUE; |
| 105 | |
| 106 | case 0x43: /* R_RL78_ABS16. */ |
| 107 | - byte_put (start + reloc->r_offset, value, 2); |
| 108 | + if (start + reloc->r_offset + 2 >= end) |
| 109 | + error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"), |
| 110 | + start + reloc->r_offset + 2, end); |
| 111 | + else |
| 112 | + byte_put (start + reloc->r_offset, value, 2); |
| 113 | value = 0; |
| 114 | return TRUE; |
| 115 | |
| 116 | @@ -12074,7 +12094,7 @@ apply_relocations (void * file, |
| 117 | |
| 118 | reloc_type = get_reloc_type (rp->r_info); |
| 119 | |
| 120 | - if (target_specific_reloc_handling (rp, start, symtab)) |
| 121 | + if (target_specific_reloc_handling (rp, start, end, symtab)) |
| 122 | continue; |
| 123 | else if (is_none_reloc (reloc_type)) |
| 124 | continue; |
| 125 | -- |
| 126 | 2.11.0 |
| 127 | |