[PATCH RFC 30/43] x86/bpf: Adapt BPF_CALL JIT codegen for PIE support

From: Hou Wenlong
Date: Fri Apr 28 2023 - 05:55:25 EST


If image is NULL, ip calculated is in bottom address and func is in
kernel image address, then the offset is valid when the kernel stays in
the top 2G address space. However, PIE kernel image could be below top
2G, which makes the offset out of range. Since the length of
PC-relative call instruction is fixed, it's pointless to calculate the
offset without the proper image base (it has been zero until the last
pass). Use 1 as the dummy offset to generate the instruction in the
first pass.

Signed-off-by: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx>
Cc: Thomas Garnier <thgarnie@xxxxxxxxxxxx>
Cc: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx>
Cc: Kees Cook <keescook@xxxxxxxxxxxx>
---
arch/x86/net/bpf_jit_comp.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 1056bbf55b17..0da41833e426 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1549,8 +1549,21 @@ st: if (is_imm8(insn->off))
return -EINVAL;
offs = x86_call_depth_emit_accounting(&prog, func);
}
- if (emit_call(&prog, func, image + addrs[i - 1] + offs))
- return -EINVAL;
+ /*
+ * If image is NULL, ip is in bottom address and func
+ * is in kernel image address (top 2G), so the offset
+ * is valid. However, PIE kernel image could be below
+ * top 2G, then the offset would be out of range. Since
+ * the length of PC-relative call(0xe8) is fixed, so it's
+ * pointless to calculate the offset until the last pass.
+ * Use 1 as the dummy offset if image is NULL.
+ */
+ if (image)
+ err = emit_call(&prog, func, image + addrs[i - 1] + offs);
+ else
+ err = emit_call(&prog, (void *)(X86_PATCH_SIZE + 1UL), 0);
+ if (err)
+ return err;
break;
}

--
2.31.1