mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 19:50:13 +08:00
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.
This commit is contained in:
@ -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>
|
2017-01-27 Dilyan Palauzov <dilyan.palauzov@aegee.org>
|
||||||
Nick Clifton <nickc@redhat.com>
|
Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
@ -11591,6 +11591,7 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
|
|||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
unsigned char * start,
|
unsigned char * start,
|
||||||
|
unsigned char * end,
|
||||||
Elf_Internal_Sym * symtab)
|
Elf_Internal_Sym * symtab)
|
||||||
{
|
{
|
||||||
unsigned int reloc_type = get_reloc_type (reloc->r_info);
|
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:
|
handle_sym_diff:
|
||||||
if (saved_sym != NULL)
|
if (saved_sym != NULL)
|
||||||
{
|
{
|
||||||
|
int reloc_size = reloc_type == 1 ? 4 : 2;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
|
|
||||||
value = reloc->r_addend
|
value = reloc->r_addend
|
||||||
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
||||||
- saved_sym->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;
|
saved_sym = NULL;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -11668,13 +11675,18 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
|||||||
case 2: /* R_MN10300_16 */
|
case 2: /* R_MN10300_16 */
|
||||||
if (saved_sym != NULL)
|
if (saved_sym != NULL)
|
||||||
{
|
{
|
||||||
|
int reloc_size = reloc_type == 1 ? 4 : 2;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
|
|
||||||
value = reloc->r_addend
|
value = reloc->r_addend
|
||||||
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
||||||
- saved_sym->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;
|
saved_sym = NULL;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -11709,12 +11721,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x41: /* R_RL78_ABS32. */
|
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;
|
value = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0x43: /* R_RL78_ABS16. */
|
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;
|
value = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -12340,7 +12360,7 @@ apply_relocations (void * file,
|
|||||||
|
|
||||||
reloc_type = get_reloc_type (rp->r_info);
|
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;
|
continue;
|
||||||
else if (is_none_reloc (reloc_type))
|
else if (is_none_reloc (reloc_type))
|
||||||
continue;
|
continue;
|
||||||
|
Reference in New Issue
Block a user