The BPF_MOV64_PERCPU_REG insn requires JIT to emit native code to for
'dst_reg = src_reg + <percpu_base_off>'.

However, the interpreter ignores the 'off' at its ALU64_MOV_K label.
The 'off' indicates the insn is BPF_MOV64_PERCPU_REG insn. Then, when
the interpreter loads memory from the register, it will hit a page
fault.

[    2.545572] BUG: unable to handle page fault for address: ffffffffacaaf034
[    2.546485] #PF: supervisor read access in kernel mode
[    2.547167] #PF: error_code(0x0000) - not-present page
[    2.547850] PGD 134e63067 P4D 134e63067 PUD 134e64063 PMD 10021c063 PTE 
800ffffeca550062
[    2.548912] Oops: Oops: 0000 [#1] SMP PTI

On the fallback path from JIT in __bpf_prog_select_runtime(), reject
the BPF_MOV64_PERCPU_REG insn to avoid the page fault.

Fixes: 7bdbf7446305 ("bpf: add special internal-only MOV instruction to resolve 
per-CPU addrs")
Signed-off-by: Leon Hwang <[email protected]>
---
 kernel/bpf/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 37b2fac22aa2..900ba10e1de9 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2610,6 +2610,9 @@ static struct bpf_prog *bpf_prog_jit_compile(struct 
bpf_verifier_env *env, struc
 
 static bool bpf_insn_requires_jit(struct bpf_insn *insn)
 {
+       if (insn_is_mov_percpu_addr(insn))
+               return true;
+
        if (insn_is_cast_user(insn))
                return true;
 
-- 
2.54.0


Reply via email to