aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-07-05 16:31:30 +0930
committerAlan Modra <amodra@gmail.com>2021-07-05 21:39:33 +0930
commitb4c4b8aaad84853ddf1b2779a5f1bbe5be157397 (patch)
treee01cce20071d44ecad07c05d72a7ea7597844356
parent40e1d303cedca7d67f6219686f06b9750659beab (diff)
downloadfsf-binutils-gdb-b4c4b8aaad84853ddf1b2779a5f1bbe5be157397.zip
fsf-binutils-gdb-b4c4b8aaad84853ddf1b2779a5f1bbe5be157397.tar.gz
fsf-binutils-gdb-b4c4b8aaad84853ddf1b2779a5f1bbe5be157397.tar.bz2
PR28055, segfault in bpf special reloc function
The testcase in this PR tickled two bugs fixed here. output_bfd is NULL when a reloc special_function is called for final linking and when called from bfd_generic_get_relocated_section_contents. Clearly using output_bfd is wrong as it results in segfaults. Not only that, the endianness of the reloc field really should be that of the input. The second bug was not checking that the entire reloc field was contained in the section contents. PR 28055 * elf64-bpf.c (bpf_elf_generic_reloc): Use correct bfd for bfd_put and bfd_put_32 calls. Correct section limit checks.
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf64-bpf.c21
2 files changed, 21 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4055369..f688d5c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2021-07-05 Alan Modra <amodra@gmail.com>
+
+ PR 28055
+ * elf64-bpf.c (bpf_elf_generic_reloc): Use correct bfd for bfd_put
+ and bfd_put_32 calls. Correct section limit checks.
+
2021-07-03 Nick Clifton <nickc@redhat.com>
* version.m4: Update version number.
diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
index 28c1543..243df93 100644
--- a/bfd/elf64-bpf.c
+++ b/bfd/elf64-bpf.c
@@ -589,14 +589,15 @@ elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
}
/* A generic howto special function for installing BPF relocations.
- This function will be called by the assembler (via bfd_install_relocation).
+ This function will be called by the assembler (via bfd_install_relocation),
+ and by various get_relocated_section_contents functions.
At link time, bpf_elf_relocate_section will resolve the final relocations.
BPF instructions are always big endian, and this approach avoids problems in
bfd_install_relocation. */
static bfd_reloc_status_type
-bpf_elf_generic_reloc (bfd * abfd, arelent *reloc_entry, asymbol *symbol,
+bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
void *data, asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
@@ -607,7 +608,15 @@ bpf_elf_generic_reloc (bfd * abfd, arelent *reloc_entry, asymbol *symbol,
bfd_byte *where;
/* Sanity check that the address is in range. */
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (reloc_entry->howto->type == R_BPF_INSN_64)
+ {
+ bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section);
+ if (reloc_entry->address > end
+ || end - reloc_entry->address < 16)
+ return bfd_reloc_outofrange;
+ }
+ else if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section,
+ reloc_entry->address))
return bfd_reloc_outofrange;
/* Get the symbol value. */
@@ -640,15 +649,15 @@ bpf_elf_generic_reloc (bfd * abfd, arelent *reloc_entry, asymbol *symbol,
instructions, and the upper 32 bits placed at the very end of the
instruction. that is, there are 32 unused bits between them. */
- bfd_put_32 (output_bfd, (relocation & 0xFFFFFFFF), where + 4);
- bfd_put_32 (output_bfd, (relocation >> 32), where + 12);
+ bfd_put_32 (abfd, (relocation & 0xFFFFFFFF), where + 4);
+ bfd_put_32 (abfd, (relocation >> 32), where + 12);
}
else
{
/* For other kinds of relocations, the relocated value simply goes
BITPOS bits from the start of the entry. This is always a multiple
of 8, i.e. whole bytes. */
- bfd_put (reloc_entry->howto->bitsize, output_bfd, relocation,
+ bfd_put (reloc_entry->howto->bitsize, abfd, relocation,
where + reloc_entry->howto->bitpos / 8);
}