summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2025-09-18 19:18:34 -0700
committerAlexei Starovoitov <ast@kernel.org>2025-09-19 09:27:22 -0700
commitdaf4c2929fb792d24af0cd7bb6ca1f2949190fa4 (patch)
treea7e7cbc3b560194334c9099776a9fbc5c77929fe /kernel
parent8cd189e414bb705312fbfff7f7b5605f6de2459a (diff)
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/log.c6
-rw-r--r--kernel/bpf/verifier.c13
2 files changed, 6 insertions, 13 deletions
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index e4983c1303e7..0d6d7bfb2fd0 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -545,14 +545,12 @@ static char slot_type_char[] = {
static void print_liveness(struct bpf_verifier_env *env,
enum bpf_reg_liveness live)
{
- if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN | REG_LIVE_DONE))
- verbose(env, "_");
+ if (live & (REG_LIVE_READ | REG_LIVE_WRITTEN))
+ verbose(env, "_");
if (live & REG_LIVE_READ)
verbose(env, "r");
if (live & REG_LIVE_WRITTEN)
verbose(env, "w");
- if (live & REG_LIVE_DONE)
- verbose(env, "D");
}
#define UNUM_MAX_DECIMAL U16_MAX
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index aef6b266f08d..47cec5c8abff 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1758,6 +1758,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
return err;
dst_state->speculative = src->speculative;
dst_state->in_sleepable = src->in_sleepable;
+ dst_state->cleaned = src->cleaned;
dst_state->curframe = src->curframe;
dst_state->branches = src->branches;
dst_state->parent = src->parent;
@@ -3589,11 +3590,6 @@ static int mark_reg_read(struct bpf_verifier_env *env,
/* if read wasn't screened by an earlier write ... */
if (writes && state->live & REG_LIVE_WRITTEN)
break;
- if (verifier_bug_if(parent->live & REG_LIVE_DONE, env,
- "type %s var_off %lld off %d",
- reg_type_str(env, parent->type),
- parent->var_off.value, parent->off))
- return -EFAULT;
/* The first condition is more likely to be true than the
* second, checked it first.
*/
@@ -18501,7 +18497,6 @@ static void clean_func_state(struct bpf_verifier_env *env,
for (i = 0; i < BPF_REG_FP; i++) {
live = st->regs[i].live;
/* liveness must not touch this register anymore */
- st->regs[i].live |= REG_LIVE_DONE;
if (!(live & REG_LIVE_READ))
/* since the register is unused, clear its state
* to make further comparison simpler
@@ -18512,7 +18507,6 @@ static void clean_func_state(struct bpf_verifier_env *env,
for (i = 0; i < st->allocated_stack / BPF_REG_SIZE; i++) {
live = st->stack[i].spilled_ptr.live;
/* liveness must not touch this stack slot anymore */
- st->stack[i].spilled_ptr.live |= REG_LIVE_DONE;
if (!(live & REG_LIVE_READ)) {
__mark_reg_not_init(env, &st->stack[i].spilled_ptr);
for (j = 0; j < BPF_REG_SIZE; j++)
@@ -18526,6 +18520,7 @@ static void clean_verifier_state(struct bpf_verifier_env *env,
{
int i;
+ st->cleaned = true;
for (i = 0; i <= st->curframe; i++)
clean_func_state(env, st->frame[i]);
}
@@ -18553,7 +18548,7 @@ static void clean_verifier_state(struct bpf_verifier_env *env,
* their final liveness marks are already propagated.
* Hence when the verifier completes the search of state list in is_state_visited()
* we can call this clean_live_states() function to mark all liveness states
- * as REG_LIVE_DONE to indicate that 'parent' pointers of 'struct bpf_reg_state'
+ * as st->cleaned to indicate that 'parent' pointers of 'struct bpf_reg_state'
* will not be used.
* This function also clears the registers and stack for states that !READ
* to simplify state merging.
@@ -18576,7 +18571,7 @@ static void clean_live_states(struct bpf_verifier_env *env, int insn,
if (sl->state.insn_idx != insn ||
!same_callsites(&sl->state, cur))
continue;
- if (sl->state.frame[0]->regs[0].live & REG_LIVE_DONE)
+ if (sl->state.cleaned)
/* all regs in this state in all frames were already marked */
continue;
if (incomplete_read_marks(env, &sl->state))