bpf: Attribute async callback instructions to verification roots

Asynchronous callbacks are explored as fresh frame-zero verifier states,
so normal callee-to-caller accounting cannot propagate their instruction
budget to the main or global subprogram whose verification scheduled them.

The callback exploration still happens within the same do_check_common()
invocation as that independent verification root. Record
env->insn_processed at do_check_common() entry and override the root's
inclusive count with the delta before returning. This includes all directly
and transitively scheduled asynchronous callbacks in the root's total
without maintaining a separate accounting call stack.

Static subprogram and callback totals remain local to their synchronous call
paths. Their self counts continue to account for each processed instruction
exactly once.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260812221925.3358041-3-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit is contained in:
Kumar Kartikeya Dwivedi
2026-08-13 00:19:19 +02:00
committed by Eduard Zingerman
parent 14c950ac2b
commit 6137fb7c5f

View File

@@ -18448,6 +18448,7 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
struct bpf_prog_aux *aux = env->prog->aux;
struct bpf_verifier_state *state;
struct bpf_reg_state *regs;
u32 insn_processed = env->insn_processed;
int ret, i;
env->prev_linfo = NULL;
@@ -18590,6 +18591,15 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
if (!ret && pop_log)
bpf_vlog_reset(&env->log, 0);
free_states(env);
/*
* The override is needed to account for async subprograms, which
* are verified with their own set of stack frames and thus are
* not accounted as callees by account_current_path().
* Accumulate their total counts as total counts of the main or
* global subprog hosting the async call.
*/
env->subprog_info[subprog].insns_total = env->insn_processed - insn_processed;
return ret;
}