timed may_goto passes a stack offset to the architecture trampoline,
which reconstructs the counter pointer from its BPF frame pointer. This
breaks when the JIT uses a private stack with a different frame pointer.

Resolve the counter pointer in the fixup using BPF_REG_FP and pass the
pointer through BPF_REG_AX. Account for the extra instruction in the
internal branch offsets.

Fixes: e723608bf428 ("bpf: Add verifier support for timed may_goto")
Reported-by: Jeremy Jean <[email protected]>
Link: 
https://lore.kernel.org/all/[email protected]/
Signed-off-by: Siddharth Chintamaneni <[email protected]>
---
 kernel/bpf/fixups.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index 65b441e4a351..dc59501a32bb 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -1797,20 +1797,20 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env)
                        stack_depth_extra = 16;
                        insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_AX, 
BPF_REG_10, stack_off_cnt);
                        if (insn->off >= 0)
-                               insn_buf[1] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 
0, insn->off + 5);
+                               insn_buf[1] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 
0, insn->off + 6);
                        else
                                insn_buf[1] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_AX, 
0, insn->off - 1);
                        insn_buf[2] = BPF_ALU64_IMM(BPF_SUB, BPF_REG_AX, 1);
-                       insn_buf[3] = BPF_JMP_IMM(BPF_JNE, BPF_REG_AX, 0, 2);
+                       insn_buf[3] = BPF_JMP_IMM(BPF_JNE, BPF_REG_AX, 0, 3);
                        /*
-                        * AX is used as an argument to pass in stack_off_cnt
-                        * (to add to r10/fp), and also as the return value of
-                        * the call to arch_bpf_timed_may_goto.
+                        * AX is used to pass FP + stack_off_cnt as the 
argument to
+                        * arch_bpf_timed_may_goto(), and also holds its return 
value.
                         */
-                       insn_buf[4] = BPF_MOV64_IMM(BPF_REG_AX, stack_off_cnt);
-                       insn_buf[5] = BPF_EMIT_CALL(arch_bpf_timed_may_goto);
-                       insn_buf[6] = BPF_STX_MEM(BPF_DW, BPF_REG_10, 
BPF_REG_AX, stack_off_cnt);
-                       cnt = 7;
+                       insn_buf[4] = BPF_MOV64_REG(BPF_REG_AX, BPF_REG_FP);
+                       insn_buf[5] = BPF_ALU64_IMM(BPF_ADD, BPF_REG_AX, 
stack_off_cnt);
+                       insn_buf[6] = BPF_EMIT_CALL(arch_bpf_timed_may_goto);
+                       insn_buf[7] = BPF_STX_MEM(BPF_DW, BPF_REG_10, 
BPF_REG_AX, stack_off_cnt);
+                       cnt = 8;
 
                        new_prog = bpf_patch_insn_data(env, i + delta, 
insn_buf, cnt);
                        if (!new_prog)
@@ -2661,4 +2661,3 @@ int bpf_remove_fastcall_spills_fills(struct 
bpf_verifier_env *env)
 
        return 0;
 }
-
-- 
2.43.0

Reply via email to