diff options
author | Nick Clifton <nickc@redhat.com> | 2017-02-13 13:08:32 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2017-02-13 13:08:32 +0000 |
commit | 03f7786e2f440b9892b1c34a58fb26222ce1b493 (patch) | |
tree | 971cf273051f9b7249a1e3ac3287109160a52eae | |
parent | 13a590ca65f744c8fa55d6e0748cb12f443493f0 (diff) | |
download | gdb-03f7786e2f440b9892b1c34a58fb26222ce1b493.zip gdb-03f7786e2f440b9892b1c34a58fb26222ce1b493.tar.gz gdb-03f7786e2f440b9892b1c34a58fb26222ce1b493.tar.bz2 |
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.
-rw-r--r-- | binutils/ChangeLog | 7 | ||||
-rw-r--r-- | binutils/readelf.c | 30 |
2 files changed, 32 insertions, 5 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index a734433..6480c8f 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-01-27 Dilyan Palauzov <dilyan.palauzov@aegee.org> Nick Clifton <nickc@redhat.com> diff --git a/binutils/readelf.c b/binutils/readelf.c index b488714..e474f27 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -11591,6 +11591,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); @@ -11631,13 +11632,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; @@ -11668,13 +11675,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; @@ -11709,12 +11721,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; @@ -12340,7 +12360,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; |