Re: [PATCH] bpf: net_sched: reject bpf_throw() in qdisc teardown callbacks

From: Alexei Starovoitov

Date: Tue Nov 03 2026 - 13:19:31 EST


On Tue, Nov 03, 2026 at 09:32 AM shaos <shawnq1@xxxxxxx> wrote:
> A BPF qdisc's generated reset/destroy epilogue cancels its watchdog
> timer. bpf_throw() unwinds directly to the exception callback and
> skips that epilogue.

That's a bug in the verifier. bpf_qdisc.c is the wrong place to fix it.
gen_epilogue() is a contract: the epilogue runs before the prog returns.
bpf_convert_ctx_accesses() puts the epilogue in place of BPF_EXIT
in the main prog only. The exception callback is a subprog.
So bpf_throw() breaks the contract for every gen_epilogue() user,
bpf_testmod included. Fix it there.
Then bpf_qdisc.c doesn't need to know about bpf_throw: no BTF id,
no QDISC_OPS_KF_TEARDOWN, no forward declaration.

Like:

diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index ead7871..5363e88 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -909,6 +909,11 @@ int bpf_convert_ctx_accesses(struct bpf_verifier_env *env)
verifier_bug(env, "epilogue is too long");
return -EFAULT;
} else if (epilogue_cnt) {
+ /* bpf_throw() leaves via the exception callback */
+ if (env->seen_exception) {
+ verbose(env, "bpf_throw would skip the epilogue of the program\n");
+ return -EINVAL;
+ }
/* Save the ARG_PTR_TO_CTX for the epilogue to use */
subprogs[0].stack_depth += 8;
insn_buf[0] = BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_1,


> Fixes: 7a2dafda950b ("bpf: net_sched: Add a qdisc watchdog timer")

With the fix in the verifier it's
Fixes: 169c31761c8d ("bpf: Add gen_epilogue to bpf_verifier_ops")

Pls add a selftest as patch 2. bpf_testmod_st_ops has gen_epilogue().
A test_epilogue prog that calls bpf_throw(), with __failure and __msg(),
is enough. See progs/epilogue_exit.c.

Pls target bpf-next and cc ameryhung@xxxxxxxxx on respin.

pw-bot: cr