Skip to content

Commit ddbed3b

Browse files
anakryikogregkh
authored andcommitted
bpf: propagate precision across all frames, not just the last one
[ Upstream commit 529409e ] When equivalent completed state is found and it has additional precision restrictions, BPF verifier propagates precision to currently-being-verified state chain (i.e., including parent states) so that if some of the states in the chain are not yet completed, necessary precision restrictions are enforced. Unfortunately, right now this happens only for the last frame (deepest active subprogram's frame), not all the frames. This can lead to incorrect matching of states due to missing precision marker. Currently this doesn't seem possible as BPF verifier forces everything to precise when validated BPF program has any subprograms. But with the next patch lifting this restriction, this becomes problematic. In fact, without this fix, we'll start getting failure in one of the existing test_verifier test cases: #906/p precise: cross frame pruning FAIL Unexpected success to load! verification time 48 usec stack depth 0+0 processed 26 insns (limit 1000000) max_states_per_insn 3 total_states 17 peak_states 17 mark_read 8 This patch adds precision propagation across all frames. Fixes: a3ce685 ("bpf: fix precision tracking") Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 3a59f8b commit ddbed3b

File tree

1 file changed

+39
-32
lines changed

1 file changed

+39
-32
lines changed

kernel/bpf/verifier.c

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,7 +2768,7 @@ static void mark_all_scalars_precise(struct bpf_verifier_env *env,
27682768
}
27692769
}
27702770

2771-
static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
2771+
static int __mark_chain_precision(struct bpf_verifier_env *env, int frame, int regno,
27722772
int spi)
27732773
{
27742774
struct bpf_verifier_state *st = env->cur_state;
@@ -2785,7 +2785,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
27852785
if (!env->bpf_capable)
27862786
return 0;
27872787

2788-
func = st->frame[st->curframe];
2788+
func = st->frame[frame];
27892789
if (regno >= 0) {
27902790
reg = &func->regs[regno];
27912791
if (reg->type != SCALAR_VALUE) {
@@ -2866,7 +2866,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
28662866
break;
28672867

28682868
new_marks = false;
2869-
func = st->frame[st->curframe];
2869+
func = st->frame[frame];
28702870
bitmap_from_u64(mask, reg_mask);
28712871
for_each_set_bit(i, mask, 32) {
28722872
reg = &func->regs[i];
@@ -2932,12 +2932,17 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
29322932

29332933
int mark_chain_precision(struct bpf_verifier_env *env, int regno)
29342934
{
2935-
return __mark_chain_precision(env, regno, -1);
2935+
return __mark_chain_precision(env, env->cur_state->curframe, regno, -1);
29362936
}
29372937

2938-
static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi)
2938+
static int mark_chain_precision_frame(struct bpf_verifier_env *env, int frame, int regno)
29392939
{
2940-
return __mark_chain_precision(env, -1, spi);
2940+
return __mark_chain_precision(env, frame, regno, -1);
2941+
}
2942+
2943+
static int mark_chain_precision_stack_frame(struct bpf_verifier_env *env, int frame, int spi)
2944+
{
2945+
return __mark_chain_precision(env, frame, -1, spi);
29412946
}
29422947

29432948
static bool is_spillable_regtype(enum bpf_reg_type type)
@@ -11856,34 +11861,36 @@ static int propagate_precision(struct bpf_verifier_env *env,
1185611861
{
1185711862
struct bpf_reg_state *state_reg;
1185811863
struct bpf_func_state *state;
11859-
int i, err = 0;
11864+
int i, err = 0, fr;
1186011865

11861-
state = old->frame[old->curframe];
11862-
state_reg = state->regs;
11863-
for (i = 0; i < BPF_REG_FP; i++, state_reg++) {
11864-
if (state_reg->type != SCALAR_VALUE ||
11865-
!state_reg->precise)
11866-
continue;
11867-
if (env->log.level & BPF_LOG_LEVEL2)
11868-
verbose(env, "propagating r%d\n", i);
11869-
err = mark_chain_precision(env, i);
11870-
if (err < 0)
11871-
return err;
11872-
}
11866+
for (fr = old->curframe; fr >= 0; fr--) {
11867+
state = old->frame[fr];
11868+
state_reg = state->regs;
11869+
for (i = 0; i < BPF_REG_FP; i++, state_reg++) {
11870+
if (state_reg->type != SCALAR_VALUE ||
11871+
!state_reg->precise)
11872+
continue;
11873+
if (env->log.level & BPF_LOG_LEVEL2)
11874+
verbose(env, "frame %d: propagating r%d\n", i, fr);
11875+
err = mark_chain_precision_frame(env, fr, i);
11876+
if (err < 0)
11877+
return err;
11878+
}
1187311879

11874-
for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) {
11875-
if (!is_spilled_reg(&state->stack[i]))
11876-
continue;
11877-
state_reg = &state->stack[i].spilled_ptr;
11878-
if (state_reg->type != SCALAR_VALUE ||
11879-
!state_reg->precise)
11880-
continue;
11881-
if (env->log.level & BPF_LOG_LEVEL2)
11882-
verbose(env, "propagating fp%d\n",
11883-
(-i - 1) * BPF_REG_SIZE);
11884-
err = mark_chain_precision_stack(env, i);
11885-
if (err < 0)
11886-
return err;
11880+
for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) {
11881+
if (!is_spilled_reg(&state->stack[i]))
11882+
continue;
11883+
state_reg = &state->stack[i].spilled_ptr;
11884+
if (state_reg->type != SCALAR_VALUE ||
11885+
!state_reg->precise)
11886+
continue;
11887+
if (env->log.level & BPF_LOG_LEVEL2)
11888+
verbose(env, "frame %d: propagating fp%d\n",
11889+
(-i - 1) * BPF_REG_SIZE, fr);
11890+
err = mark_chain_precision_stack_frame(env, fr, i);
11891+
if (err < 0)
11892+
return err;
11893+
}
1188711894
}
1188811895
return 0;
1188911896
}

0 commit comments

Comments
 (0)