mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
bpf: backtrack_insn(): Handle ld_{abs,ind} subprog exit edge
Nicholas Carlini reported a bug in precision backtracking mechanism
for BPF_LD | BPF_{IND,ABS} instructions. These instructions are
modelled as two branches:
- fallthrough;
- implicit exit from current subprogram.
The implicit exit case was not handled by the backtrack_insn()
function. When backtracking such a path backtrack_insn() did not
call bt_subprog_enter(), which meant that backtracking continued
manipulating precision marks in a caller frame, while looking at
instructions in a callee frame.
This lead to segmentation faults during verification (see the
selftest), or unsound state pruning.
Fixes: ee861486e3 ("bpf: Fix ld_{abs,ind} failure path analysis in subprogs")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20260901-bug-016-backtrack-ld-abs-v1-1-59368f1be435@gmail.com
This commit is contained in:
parent
28d75dd3eb
commit
387b1baefb
|
|
@ -582,16 +582,29 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|||
*/
|
||||
}
|
||||
} else if (class == BPF_LD) {
|
||||
if (!bt_is_reg_set(bt, dreg))
|
||||
return 0;
|
||||
bt_clear_reg(bt, dreg);
|
||||
/* It's ld_imm64 or ld_abs or ld_ind.
|
||||
* For ld_imm64 no further tracking of precision
|
||||
* into parent is necessary
|
||||
*/
|
||||
if (mode == BPF_IND || mode == BPF_ABS)
|
||||
/* to be analyzed */
|
||||
return -ENOTSUPP;
|
||||
if (mode == BPF_IMM) {
|
||||
bt_clear_reg(bt, dreg);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* BPF_{IND,ABS} are modelled as two branches:
|
||||
* - fallthrough;
|
||||
* - implicit subprogram exit.
|
||||
* It is necessary to switch current frame if
|
||||
* implicit subprogram exit branch is backtracked.
|
||||
*/
|
||||
if (mode == BPF_IND || mode == BPF_ABS) {
|
||||
if (bt_is_reg_set(bt, dreg))
|
||||
return -ENOTSUPP;
|
||||
if (subseq_idx != idx + 1)
|
||||
if (bt_subprog_enter(bt))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Propagate precision marks to linked registers, to account for
|
||||
* registers marked as precise in this function.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user