[PATCH] bpf: fix false overflow in eBPF ELF backend linker
David Faust
david.faust@oracle.com
Fri Aug 7 17:56:12 GMT 2020
When performing DISP{16,32} relocations, the eBPF ELF backend linker
needs to convert the relocation from an address into a signed number
of 64-bit words (minus one) to jump.
Because of this unsigned-to-signed conversion, special care needs to
be taken when dividing to ensure the sign bits remain correct.
Otherwise, a false relocation overflow error can be triggered.
bfd/ChangeLog
2020-08-07 David Faust <david.faust@oracle.com>
* elf64-bpf.c (bpf_elf_relocate_section): Ensure signed division for
DISP16 and DISP32 relocations.
ld/ChangeLog
2020-08-07 David Faust <david.faust@oracle.com>
* testsuite/ld-bpf/call-3.s: New file.
* testsuite/ld-bpf/call-3.d: Likewise.
---
bfd/elf64-bpf.c | 8 +++++---
ld/testsuite/ld-bpf/call-3.d | 19 +++++++++++++++++++
ld/testsuite/ld-bpf/call-3.s | 12 ++++++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
create mode 100644 ld/testsuite/ld-bpf/call-3.d
create mode 100644 ld/testsuite/ld-bpf/call-3.s
diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
index c6a726d932..657cf0d9de 100644
--- a/bfd/elf64-bpf.c
+++ b/bfd/elf64-bpf.c
@@ -443,9 +443,11 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
{
/* Make the relocation PC-relative, and change its unit to
64-bit words. */
- relocation -= sec_addr (input_section) + rel->r_offset;
- /* Make it 64-bit words. */
- relocation = relocation / 8;
+ relocation = ((bfd_signed_vma) relocation
+ - (sec_addr (input_section) + rel->r_offset));
+
+ /* Make it 64-bit words, but beware we need *signed* division. */
+ relocation = (bfd_signed_vma) relocation / 8;
/* Get the addend from the instruction and apply it. */
addend = bfd_get (howto->bitsize, input_bfd,
diff --git a/ld/testsuite/ld-bpf/call-3.d b/ld/testsuite/ld-bpf/call-3.d
new file mode 100644
index 0000000000..d371cd7d44
--- /dev/null
+++ b/ld/testsuite/ld-bpf/call-3.d
@@ -0,0 +1,19 @@
+#as: --EL
+#source: call-3.s
+#objdump: -dr
+#ld: -EL
+#name: CALL check unsigned underflow
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <bar>:
+ *[0-9a-f]+: b7 00 00 00 00 00 00 00 mov %r0,0
+ *[0-9a-f]+: 95 00 00 00 00 00 00 00 exit
+
+[0-9a-f]+ <main>:
+ *[0-9a-f]+: b7 00 00 00 03 00 00 00 mov %r0,3
+ *[0-9a-f]+: b7 01 00 00 01 00 00 00 mov %r1,1
+ *[0-9a-f]+: 85 10 00 00 fb ff ff ff call -5
+ *[0-9a-f]+: 95 00 00 00 00 00 00 00 exit
diff --git a/ld/testsuite/ld-bpf/call-3.s b/ld/testsuite/ld-bpf/call-3.s
new file mode 100644
index 0000000000..d4c042cba8
--- /dev/null
+++ b/ld/testsuite/ld-bpf/call-3.s
@@ -0,0 +1,12 @@
+ .text
+ .align 4
+ .global bar
+bar:
+ mov %r0, 0
+ exit
+
+main:
+ mov %r0, 3
+ mov %r1, 1
+ call bar
+ exit
--
2.26.2
More information about the Binutils
mailing list