Skip to content

Commit daf4c29

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
bpf: bpf_verifier_state->cleaned flag instead of REG_LIVE_DONE
Prepare for bpf_reg_state->live field removal by introducing a separate flag to track if clean_verifier_state() had been applied to the state. No functional changes. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20250918-callchain-sensitive-liveness-v3-1-c3cd27bacc60@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 8cd189e commit daf4c29

File tree

3 files changed

+7
-14
lines changed

3 files changed

+7
-14
lines changed

include/linux/bpf_verifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ enum bpf_reg_liveness {
4545
REG_LIVE_READ64 = 0x2, /* likewise, but full 64-bit content matters */
4646
REG_LIVE_READ = REG_LIVE_READ32 | REG_LIVE_READ64,
4747
REG_LIVE_WRITTEN = 0x4, /* reg was written first, screening off later reads */
48-
REG_LIVE_DONE = 0x8, /* liveness won't be updating this register anymore */
4948
};
5049

5150
#define ITER_PREFIX "bpf_iter_"
@@ -445,6 +444,7 @@ struct bpf_verifier_state {
445444

446445
bool speculative;
447446
bool in_sleepable;
447+
bool cleaned;
448448

449449
/* first and last insn idx of this verifier state */
450450
u32 first_insn_idx;

kernel/bpf/log.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,14 +545,12 @@ static char slot_type_char[] = {
545545
static void print_liveness(struct bpf_verifier_env *env,
546546
enum bpf_reg_liveness live)
547547
{
548-
if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN | REG_LIVE_DONE))
549-
verbose(env, "_");
548+
if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN))
549+
verbose(env, "_");
550550
if (live & REG_LIVE_READ)
551551
verbose(env, "r");
552552
if (live & REG_LIVE_WRITTEN)
553553
verbose(env, "w");
554-
if (live & REG_LIVE_DONE)
555-
verbose(env, "D");
556554
}
557555

558556
#define UNUM_MAX_DECIMAL U16_MAX

kernel/bpf/verifier.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
17581758
return err;
17591759
dst_state->speculative = src->speculative;
17601760
dst_state->in_sleepable = src->in_sleepable;
1761+
dst_state->cleaned = src->cleaned;
17611762
dst_state->curframe = src->curframe;
17621763
dst_state->branches = src->branches;
17631764
dst_state->parent = src->parent;
@@ -3589,11 +3590,6 @@ static int mark_reg_read(struct bpf_verifier_env *env,
35893590
/* if read wasn't screened by an earlier write ... */
35903591
if (writes && state->live & REG_LIVE_WRITTEN)
35913592
break;
3592-
if (verifier_bug_if(parent->live & REG_LIVE_DONE, env,
3593-
"type %s var_off %lld off %d",
3594-
reg_type_str(env, parent->type),
3595-
parent->var_off.value, parent->off))
3596-
return -EFAULT;
35973593
/* The first condition is more likely to be true than the
35983594
* second, checked it first.
35993595
*/
@@ -18501,7 +18497,6 @@ static void clean_func_state(struct bpf_verifier_env *env,
1850118497
for (i = 0; i < BPF_REG_FP; i++) {
1850218498
live = st->regs[i].live;
1850318499
/* liveness must not touch this register anymore */
18504-
st->regs[i].live |= REG_LIVE_DONE;
1850518500
if (!(live & REG_LIVE_READ))
1850618501
/* since the register is unused, clear its state
1850718502
* to make further comparison simpler
@@ -18512,7 +18507,6 @@ static void clean_func_state(struct bpf_verifier_env *env,
1851218507
for (i = 0; i < st->allocated_stack / BPF_REG_SIZE; i++) {
1851318508
live = st->stack[i].spilled_ptr.live;
1851418509
/* liveness must not touch this stack slot anymore */
18515-
st->stack[i].spilled_ptr.live |= REG_LIVE_DONE;
1851618510
if (!(live & REG_LIVE_READ)) {
1851718511
__mark_reg_not_init(env, &st->stack[i].spilled_ptr);
1851818512
for (j = 0; j < BPF_REG_SIZE; j++)
@@ -18526,6 +18520,7 @@ static void clean_verifier_state(struct bpf_verifier_env *env,
1852618520
{
1852718521
int i;
1852818522

18523+
st->cleaned = true;
1852918524
for (i = 0; i <= st->curframe; i++)
1853018525
clean_func_state(env, st->frame[i]);
1853118526
}
@@ -18553,7 +18548,7 @@ static void clean_verifier_state(struct bpf_verifier_env *env,
1855318548
* their final liveness marks are already propagated.
1855418549
* Hence when the verifier completes the search of state list in is_state_visited()
1855518550
* we can call this clean_live_states() function to mark all liveness states
18556-
* as REG_LIVE_DONE to indicate that 'parent' pointers of 'struct bpf_reg_state'
18551+
* as st->cleaned to indicate that 'parent' pointers of 'struct bpf_reg_state'
1855718552
* will not be used.
1855818553
* This function also clears the registers and stack for states that !READ
1855918554
* to simplify state merging.
@@ -18576,7 +18571,7 @@ static void clean_live_states(struct bpf_verifier_env *env, int insn,
1857618571
if (sl->state.insn_idx != insn ||
1857718572
!same_callsites(&sl->state, cur))
1857818573
continue;
18579-
if (sl->state.frame[0]->regs[0].live & REG_LIVE_DONE)
18574+
if (sl->state.cleaned)
1858018575
/* all regs in this state in all frames were already marked */
1858118576
continue;
1858218577
if (incomplete_read_marks(env, &sl->state))

0 commit comments

Comments
 (0)