This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
mips_elf_create_dynamic_relocation can look beyond relocs array end
- From: Sergey Rogozhkin <rogozhkin at niisi dot msk dot ru>
- To: binutils at sourceware dot org
- Date: Sun, 29 Apr 2007 01:34:49 +0400
- Subject: mips_elf_create_dynamic_relocation can look beyond relocs array end
Hi, list.
The following code in mips_elf_create_dynamic_relocation can look beyond
relocs array end when called in such way:
_bfd_mips_elf_relocate_section -> mips_elf_calculate_relocation ->
mips_elf_create_dynamic_relocation:
outrel[1].r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel[1].r_offset);
outrel[2].r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel[2].r_offset);
This code deals with non-standard 64 bit ELF relocations format, but the
problem occurs while linking o32 or n32 objects. If rel points to the
last relocs (_bfd_mips_elf_relocate_section argument) array entry, then
access to rel[1] and rel[2] can cause segfault, or garbage can be read
and passed to _bfd_elf_section_offset, which can cause assertion fail in
_bfd_elf_eh_frame_section_offset. The last is a real case of ld behavior
at least when linking o32 shared libraries using binutils-2.17.50.0.12
(and binutils-2.17.50.0.15 also). Really
mips_elf_create_dynamic_relocation doesn't need rel[1] and rel[2]
records while working in 32 bit mode, maybe it would be better if it
doesn't access them in that case?
Sergey Rogozhkin
--- bfd/elfxx-mips.c 2007-04-19 18:14:24.000000000 +0400
+++ bfd/elfxx-mips.c 2007-04-28 16:15:23.000000000 +0400
@@ -4786,10 +4786,13 @@ mips_elf_create_dynamic_relocation (bfd
outrel[0].r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
- outrel[1].r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset);
- outrel[2].r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset);
+ if (ABI_64_P (output_bfd))
+ {
+ outrel[1].r_offset = _bfd_elf_section_offset
+ (output_bfd, info, input_section, rel[1].r_offset);
+ outrel[2].r_offset = _bfd_elf_section_offset
+ (output_bfd, info, input_section, rel[2].r_offset);
+ }
if (outrel[0].r_offset == MINUS_ONE)
/* The relocation field has been deleted. */