]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bpf: Fix out-of-bounds read in bpf_patch_call_args()
authorYazhou Tang <tangyazhou518@outlook.com>
Wed, 6 May 2026 09:47:12 +0000 (17:47 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 11 May 2026 15:27:01 +0000 (08:27 -0700)
The interpreters_args array only accommodates stack depths up to
MAX_BPF_STACK (512 bytes). However, do_misc_fixups() may allow a larger
stack depth if JIT is requested.

If JIT compilation later fails and falls back to the interpreter, the
verifier invokes bpf_patch_call_args() with this oversized stack depth.
This causes a load-time out-of-bounds (OOB) read when calculating the
interpreter function pointer index.

Fix this by changing bpf_patch_call_args() to return an int and explicitly
rejecting the JIT fallback (returning -EINVAL) if the stack depth exceeds
MAX_BPF_STACK.

Fixes: 1ea47e01ad6e ("bpf: add support for bpf_call to interpreter")
Co-developed-by: Tianci Cao <ziye@zju.edu.cn>
Signed-off-by: Tianci Cao <ziye@zju.edu.cn>
Co-developed-by: Shenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: Shenghao Yuan <shenghaoyuan0928@163.com>
Signed-off-by: Yazhou Tang <tangyazhou518@outlook.com>
Acked-by: Xu Kuohai <xukuohai@huawei.com>
Link: https://lore.kernel.org/r/20260506094714.419842-2-tangyazhou@zju.edu.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/bpf.h
kernel/bpf/core.c
kernel/bpf/fixups.c

index 01e20396489287269f4ed940a2593677e9c40d58..52b30e9ea431b5acaed6cc50622affd592a69c26 100644 (file)
@@ -2917,7 +2917,7 @@ int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
 int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size);
 
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
-void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
+int bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
 #endif
 
 struct btf *bpf_get_btf_vmlinux(void);
index 8b018ff488750b46b64dfea6fee051d81bcaa5d1..63044ebe572134506d14724048f7ae9feaa73d43 100644 (file)
@@ -2394,13 +2394,17 @@ EVAL4(PROG_NAME_LIST, 416, 448, 480, 512)
 #undef PROG_NAME_LIST
 
 #ifdef CONFIG_BPF_SYSCALL
-void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth)
+int bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth)
 {
        stack_depth = max_t(u32, stack_depth, 1);
+       /* Prevent out-of-bounds read to interpreters_args */
+       if (stack_depth > MAX_BPF_STACK)
+               return -EINVAL;
        insn->off = (s16) insn->imm;
        insn->imm = interpreters_args[(round_up(stack_depth, 32) / 32) - 1] -
                __bpf_call_base_args;
        insn->code = BPF_JMP | BPF_CALL_ARGS;
+       return 0;
 }
 #endif
 #endif
index fba9e8c008787547111ae60f4a508d19ea38500c..df8f48091321f7954689aef03b0dc0b75283dc8a 100644 (file)
@@ -1416,7 +1416,12 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
                depth = get_callee_stack_depth(env, insn, i);
                if (depth < 0)
                        return depth;
-               bpf_patch_call_args(insn, depth);
+               err = bpf_patch_call_args(insn, depth);
+               if (err) {
+                       verbose(env, "stack depth %d exceeds interpreter stack depth limit\n",
+                               depth);
+                       return err;
+               }
        }
        err = 0;
 #endif