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