[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