Fix read-after-free error in readelf when processing multiple, relocated sections in an MSP430 binary.
PR binutils/21139 * readelf.c (target_specific_reloc_handling): Add num_syms parameter. Check for symbol table overflow before accessing symbol value. If reloc pointer is NULL, discard all saved state. (apply_relocations): Pass num_syms to target_specific_reloc_handling. Call target_specific_reloc_handling with a NULL reloc pointer after processing all of the relocs.
This commit is contained in:
parent
5cf30ebf64
commit
f84ce13b67
|
@ -1,3 +1,13 @@
|
||||||
|
2017-02-13 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/21139
|
||||||
|
* readelf.c (target_specific_reloc_handling): Add num_syms
|
||||||
|
parameter. Check for symbol table overflow before accessing
|
||||||
|
symbol value. If reloc pointer is NULL, discard all saved state.
|
||||||
|
(apply_relocations): Pass num_syms to target_specific_reloc_handling.
|
||||||
|
Call target_specific_reloc_handling with a NULL reloc pointer
|
||||||
|
after processing all of the relocs.
|
||||||
|
|
||||||
2017-02-13 Nick Clifton <nickc@redhat.com>
|
2017-02-13 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/21137
|
PR binutils/21137
|
||||||
|
|
|
@ -11586,15 +11586,27 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
|
||||||
|
|
||||||
/* Check to see if the given reloc needs to be handled in a target specific
|
/* Check to see if the given reloc needs to be handled in a target specific
|
||||||
manner. If so then process the reloc and return TRUE otherwise return
|
manner. If so then process the reloc and return TRUE otherwise return
|
||||||
FALSE. */
|
FALSE.
|
||||||
|
|
||||||
|
If called with reloc == NULL, then this is a signal that reloc processing
|
||||||
|
for the current section has finished, and any saved state should be
|
||||||
|
discarded. */
|
||||||
|
|
||||||
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,
|
unsigned char * end,
|
||||||
Elf_Internal_Sym * symtab)
|
Elf_Internal_Sym * symtab,
|
||||||
|
unsigned long num_syms)
|
||||||
{
|
{
|
||||||
unsigned int reloc_type = get_reloc_type (reloc->r_info);
|
unsigned int reloc_type = 0;
|
||||||
|
unsigned long sym_index = 0;
|
||||||
|
|
||||||
|
if (reloc)
|
||||||
|
{
|
||||||
|
reloc_type = get_reloc_type (reloc->r_info);
|
||||||
|
sym_index = get_reloc_symindex (reloc->r_info);
|
||||||
|
}
|
||||||
|
|
||||||
switch (elf_header.e_machine)
|
switch (elf_header.e_machine)
|
||||||
{
|
{
|
||||||
|
@ -11603,6 +11615,12 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
{
|
{
|
||||||
static Elf_Internal_Sym * saved_sym = NULL;
|
static Elf_Internal_Sym * saved_sym = NULL;
|
||||||
|
|
||||||
|
if (reloc == NULL)
|
||||||
|
{
|
||||||
|
saved_sym = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (reloc_type)
|
switch (reloc_type)
|
||||||
{
|
{
|
||||||
case 10: /* R_MSP430_SYM_DIFF */
|
case 10: /* R_MSP430_SYM_DIFF */
|
||||||
|
@ -11610,7 +11628,12 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
break;
|
break;
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
case 21: /* R_MSP430X_SYM_DIFF */
|
case 21: /* R_MSP430X_SYM_DIFF */
|
||||||
saved_sym = symtab + get_reloc_symindex (reloc->r_info);
|
/* PR 21139. */
|
||||||
|
if (sym_index >= num_syms)
|
||||||
|
error (_("MSP430 SYM_DIFF reloc contains invalid symbol index %lu\n"),
|
||||||
|
sym_index);
|
||||||
|
else
|
||||||
|
saved_sym = symtab + sym_index;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 1: /* R_MSP430_32 or R_MSP430_ABS32 */
|
case 1: /* R_MSP430_32 or R_MSP430_ABS32 */
|
||||||
|
@ -11635,16 +11658,21 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
int reloc_size = reloc_type == 1 ? 4 : 2;
|
int reloc_size = reloc_type == 1 ? 4 : 2;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
|
|
||||||
value = reloc->r_addend
|
if (sym_index >= num_syms)
|
||||||
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
error (_("MSP430 reloc contains invalid symbol index %lu\n"),
|
||||||
- saved_sym->st_value);
|
sym_index);
|
||||||
|
|
||||||
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
|
else
|
||||||
byte_put (start + reloc->r_offset, value, reloc_size);
|
{
|
||||||
|
value = reloc->r_addend + (symtab[sym_index].st_value
|
||||||
|
- saved_sym->st_value);
|
||||||
|
|
||||||
|
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;
|
||||||
|
@ -11664,13 +11692,24 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
{
|
{
|
||||||
static Elf_Internal_Sym * saved_sym = NULL;
|
static Elf_Internal_Sym * saved_sym = NULL;
|
||||||
|
|
||||||
|
if (reloc == NULL)
|
||||||
|
{
|
||||||
|
saved_sym = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (reloc_type)
|
switch (reloc_type)
|
||||||
{
|
{
|
||||||
case 34: /* R_MN10300_ALIGN */
|
case 34: /* R_MN10300_ALIGN */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case 33: /* R_MN10300_SYM_DIFF */
|
case 33: /* R_MN10300_SYM_DIFF */
|
||||||
saved_sym = symtab + get_reloc_symindex (reloc->r_info);
|
if (sym_index >= num_syms)
|
||||||
|
error (_("MN10300_SYM_DIFF reloc contains invalid symbol index %lu\n"),
|
||||||
|
sym_index);
|
||||||
|
else
|
||||||
|
saved_sym = symtab + sym_index;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 1: /* R_MN10300_32 */
|
case 1: /* R_MN10300_32 */
|
||||||
case 2: /* R_MN10300_16 */
|
case 2: /* R_MN10300_16 */
|
||||||
if (saved_sym != NULL)
|
if (saved_sym != NULL)
|
||||||
|
@ -11678,15 +11717,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
int reloc_size = reloc_type == 1 ? 4 : 2;
|
int reloc_size = reloc_type == 1 ? 4 : 2;
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
|
|
||||||
value = reloc->r_addend
|
if (sym_index >= num_syms)
|
||||||
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
error (_("MN10300 reloc contains invalid symbol index %lu\n"),
|
||||||
- saved_sym->st_value);
|
sym_index);
|
||||||
|
|
||||||
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
|
else
|
||||||
byte_put (start + reloc->r_offset, value, reloc_size);
|
{
|
||||||
|
value = reloc->r_addend + (symtab[sym_index].st_value
|
||||||
|
- saved_sym->st_value);
|
||||||
|
|
||||||
|
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;
|
||||||
|
@ -11706,12 +11750,24 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
static bfd_vma saved_sym2 = 0;
|
static bfd_vma saved_sym2 = 0;
|
||||||
static bfd_vma value;
|
static bfd_vma value;
|
||||||
|
|
||||||
|
if (reloc == NULL)
|
||||||
|
{
|
||||||
|
saved_sym1 = saved_sym2 = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (reloc_type)
|
switch (reloc_type)
|
||||||
{
|
{
|
||||||
case 0x80: /* R_RL78_SYM. */
|
case 0x80: /* R_RL78_SYM. */
|
||||||
saved_sym1 = saved_sym2;
|
saved_sym1 = saved_sym2;
|
||||||
saved_sym2 = symtab[get_reloc_symindex (reloc->r_info)].st_value;
|
if (sym_index >= num_syms)
|
||||||
saved_sym2 += reloc->r_addend;
|
error (_("RL78_SYM reloc contains invalid symbol index %lu\n"),
|
||||||
|
sym_index);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saved_sym2 = symtab[sym_index].st_value;
|
||||||
|
saved_sym2 += reloc->r_addend;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case 0x83: /* R_RL78_OPsub. */
|
case 0x83: /* R_RL78_OPsub. */
|
||||||
|
@ -12360,7 +12416,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, end, symtab))
|
if (target_specific_reloc_handling (rp, start, end, symtab, num_syms))
|
||||||
continue;
|
continue;
|
||||||
else if (is_none_reloc (reloc_type))
|
else if (is_none_reloc (reloc_type))
|
||||||
continue;
|
continue;
|
||||||
|
@ -12456,6 +12512,9 @@ apply_relocations (void * file,
|
||||||
}
|
}
|
||||||
|
|
||||||
free (symtab);
|
free (symtab);
|
||||||
|
/* Let the target specific reloc processing code know that
|
||||||
|
we have finished with these relocs. */
|
||||||
|
target_specific_reloc_handling (NULL, NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
if (relocs_return)
|
if (relocs_return)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue