SCEV needs live stack information in order to skip tracking dead slots. Liveness tracks this per function instance, but SCEV is not callchain-sensitive and needs a summary across calling contexts. For each instruction, union the current-frame liveness masks from all analyzed function instances. Represent 8-byte slots as a summary of constituent halves. Store the summary in insn_aux_data. Signed-off-by: Eduard Zingerman --- include/linux/bpf_verifier.h | 1 + kernel/bpf/liveness.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 4cb36ee3b6f7..5b615083ffa9 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -667,6 +667,7 @@ struct bpf_insn_aux_data { * that this instruction may write to. */ DECLARE_BITMAP(may_write_mask, MAX_BPF_STACK_SLOTS); + DECLARE_BITMAP(live_stack_before, MAX_BPF_STACK_SLOTS); int ctx_field_size; /* the ctx field size for load insn, maybe 0 */ u32 seen; /* this insn was processed by the verifier at env->pass_cnt */ bool nospec; /* do not execute this instruction speculatively */ diff --git a/kernel/bpf/liveness.c b/kernel/bpf/liveness.c index ec9c8beef556..004c1f48a065 100644 --- a/kernel/bpf/liveness.c +++ b/kernel/bpf/liveness.c @@ -729,8 +729,9 @@ static void half_spis_to_slots(unsigned long *slots, const unsigned long *mask, } /* - * Precompute, for each instruction, the OR of may_write masks over its top - * frame across all func_instances reaching it, stash it in the insn_aux_data. + * Precompute, for each instruction, the OR of may_write and live_before masks + * over its top frame across all func_instances reaching it, stash them in the + * insn_aux_data. */ static void compute_may_write_masks(struct bpf_verifier_env *env) { @@ -746,9 +747,12 @@ static void compute_may_write_masks(struct bpf_verifier_env *env) if (!fm) continue; nbits = frame_mask_bits(fm); - for (i = 0; i < instance->insn_cnt; i++) + for (i = 0; i < instance->insn_cnt; i++) { half_spis_to_slots(aux[instance->subprog_start + i].may_write_mask, rel_mask(fm, i, FM_MAY_WRITE), nbits); + half_spis_to_slots(aux[instance->subprog_start + i].live_stack_before, + rel_mask(fm, i, FM_LIVE_BEFORE), nbits); + } } } -- 2.53.0