Skip to content

Commit 322c741

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 07c286c commit 322c741

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
@@ -2369,7 +2369,7 @@ static void mark_all_scalars_precise(struct bpf_verifier_env *env,
23692369
}
23702370
}
23712371

2372-
static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
2372+
static int __mark_chain_precision(struct bpf_verifier_env *env, int frame, int regno,
23732373
int spi)
23742374
{
23752375
struct bpf_verifier_state *st = env->cur_state;
@@ -2386,7 +2386,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
23862386
if (!env->bpf_capable)
23872387
return 0;
23882388

2389-
func = st->frame[st->curframe];
2389+
func = st->frame[frame];
23902390
if (regno >= 0) {
23912391
reg = &func->regs[regno];
23922392
if (reg->type != SCALAR_VALUE) {
@@ -2467,7 +2467,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
24672467
break;
24682468

24692469
new_marks = false;
2470-
func = st->frame[st->curframe];
2470+
func = st->frame[frame];
24712471
bitmap_from_u64(mask, reg_mask);
24722472
for_each_set_bit(i, mask, 32) {
24732473
reg = &func->regs[i];
@@ -2533,12 +2533,17 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
25332533

25342534
static int mark_chain_precision(struct bpf_verifier_env *env, int regno)
25352535
{
2536-
return __mark_chain_precision(env, regno, -1);
2536+
return __mark_chain_precision(env, env->cur_state->curframe, regno, -1);
25372537
}
25382538

2539-
static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi)
2539+
static int mark_chain_precision_frame(struct bpf_verifier_env *env, int frame, int regno)
25402540
{
2541-
return __mark_chain_precision(env, -1, spi);
2541+
return __mark_chain_precision(env, frame, regno, -1);
2542+
}
2543+
2544+
static int mark_chain_precision_stack_frame(struct bpf_verifier_env *env, int frame, int spi)
2545+
{
2546+
return __mark_chain_precision(env, frame, -1, spi);
25422547
}
25432548

25442549
static bool is_spillable_regtype(enum bpf_reg_type type)
@@ -10543,34 +10548,36 @@ static int propagate_precision(struct bpf_verifier_env *env,
1054310548
{
1054410549
struct bpf_reg_state *state_reg;
1054510550
struct bpf_func_state *state;
10546-
int i, err = 0;
10551+
int i, err = 0, fr;
1054710552

10548-
state = old->frame[old->curframe];
10549-
state_reg = state->regs;
10550-
for (i = 0; i < BPF_REG_FP; i++, state_reg++) {
10551-
if (state_reg->type != SCALAR_VALUE ||
10552-
!state_reg->precise)
10553-
continue;
10554-
if (env->log.level & BPF_LOG_LEVEL2)
10555-
verbose(env, "propagating r%d\n", i);
10556-
err = mark_chain_precision(env, i);
10557-
if (err < 0)
10558-
return err;
10559-
}
10553+
for (fr = old->curframe; fr >= 0; fr--) {
10554+
state = old->frame[fr];
10555+
state_reg = state->regs;
10556+
for (i = 0; i < BPF_REG_FP; i++, state_reg++) {
10557+
if (state_reg->type != SCALAR_VALUE ||
10558+
!state_reg->precise)
10559+
continue;
10560+
if (env->log.level & BPF_LOG_LEVEL2)
10561+
verbose(env, "frame %d: propagating r%d\n", i, fr);
10562+
err = mark_chain_precision_frame(env, fr, i);
10563+
if (err < 0)
10564+
return err;
10565+
}
1056010566

10561-
for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) {
10562-
if (!is_spilled_reg(&state->stack[i]))
10563-
continue;
10564-
state_reg = &state->stack[i].spilled_ptr;
10565-
if (state_reg->type != SCALAR_VALUE ||
10566-
!state_reg->precise)
10567-
continue;
10568-
if (env->log.level & BPF_LOG_LEVEL2)
10569-
verbose(env, "propagating fp%d\n",
10570-
(-i - 1) * BPF_REG_SIZE);
10571-
err = mark_chain_precision_stack(env, i);
10572-
if (err < 0)
10573-
return err;
10567+
for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) {
10568+
if (!is_spilled_reg(&state->stack[i]))
10569+
continue;
10570+
state_reg = &state->stack[i].spilled_ptr;
10571+
if (state_reg->type != SCALAR_VALUE ||
10572+
!state_reg->precise)
10573+
continue;
10574+
if (env->log.level & BPF_LOG_LEVEL2)
10575+
verbose(env, "frame %d: propagating fp%d\n",
10576+
(-i - 1) * BPF_REG_SIZE, fr);
10577+
err = mark_chain_precision_stack_frame(env, fr, i);
10578+
if (err < 0)
10579+
return err;
10580+
}
1057410581
}
1057510582
return 0;
1057610583
}

0 commit comments

Comments
 (0)