Skip to content

Commit 8674e2d

Browse files
borkmanngregkh
authored andcommitted
bpf: Fix ld_{abs,ind} failure path analysis in subprogs
commit ee86148 upstream. Usage of ld_{abs,ind} instructions got extended into subprogs some time ago via commit 09b28d7 ("bpf: Add abnormal return checks."). These are only allowed in subprograms when the latter are BTF annotated and have scalar return types. The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 + exit) from legacy cBPF times. While the enforcement is on scalar return types, the verifier must also simulate the path of abnormal exit if the packet data load via ld_{abs,ind} failed. This is currently not the case. Fix it by having the verifier simulate both success and failure paths, and extend it in similar ways as we do for tail calls. The success path (r0=unknown, continue to next insn) is pushed onto stack for later validation and the r0=0 and return to the caller is done on the fall-through side. Fixes: 09b28d7 ("bpf: Add abnormal return checks.") Reported-by: STAR Labs SG <info@starlabs.sg> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov <ast@kernel.org> [ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from e40f5a6 ("bpf: correct stack liveness for tail calls"); Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack() NULL-on-failure convention. ] Signed-off-by: Philo Lu <lulie@linux.alibaba.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5003ab6 commit 8674e2d

1 file changed

Lines changed: 17 additions & 0 deletions

File tree

kernel/bpf/verifier.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16100,6 +16100,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
1610016100
mark_reg_unknown(env, regs, BPF_REG_0);
1610116101
/* ld_abs load up to 32-bit skb data. */
1610216102
regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
16103+
/*
16104+
* See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
16105+
* which must be explored by the verifier when in a subprog.
16106+
*/
16107+
if (env->cur_state->curframe) {
16108+
struct bpf_verifier_state *branch;
16109+
16110+
mark_reg_scratched(env, BPF_REG_0);
16111+
branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
16112+
if (!branch)
16113+
return -EFAULT;
16114+
mark_reg_known_zero(env, regs, BPF_REG_0);
16115+
err = prepare_func_exit(env, &env->insn_idx);
16116+
if (err)
16117+
return err;
16118+
env->insn_idx--;
16119+
}
1610316120
return 0;
1610416121
}
1610516122

0 commit comments

Comments
 (0)