Since commit d09c2aa3109f ("bpf: Track borrowed iterator results by
default"), the verifier ties a struct pointer returned by an iterator's
next kfunc to the current element by default: it is invalidated by the
following "next" call, and by "destroy".
That breaks the MPTCP BPF schedulers tests, keeping a subflow after
advancing the iterator: bpf_rr keeps the first subflow, and bpf_burst
keeps the "best" ones to use them after the loop. Both are now rejected
at load time:
R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_
(...)
# test_rr:FAIL:open_and_load: rr unexpected error: -13
The returned subflow is not tied to the iterator position: next only
walks msk->conn_list, destroy is empty, and no per-element protection
is dropped. In fact, the subflow is still valid thanks to the held msk
lock. Then declare it with KF_ITER_RET_INDEPENDENT.
Link: https://lore.kernel.org/20261024100647.2579244-2-xyx2021@mail.ustc.edu.cn
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
net/mptcp/bpf.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
index 53111d7a9eee..74648ca1e99b 100644
--- a/net/mptcp/bpf.c
+++ b/net/mptcp/bpf.c
@@ -298,7 +298,8 @@ __bpf_kfunc_end_defs();
BTF_KFUNCS_START(bpf_mptcp_iter_kfunc_ids)
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_new, KF_ITER_NEW)
-BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_next, KF_ITER_NEXT | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_next,
+ KF_ITER_NEXT | KF_RET_NULL | KF_ITER_RET_INDEPENDENT)
BTF_ID_FLAGS(func, bpf_iter_mptcp_subflow_destroy, KF_ITER_DESTROY)
BTF_KFUNCS_END(bpf_mptcp_iter_kfunc_ids)
---
base-commit: 2a3ce18c1f6d771195394b1d564947524ce774ad
change-id: 20261102-mptcp-bpf-kf-iter-ret-indep-1c54db7d436b
Best regards,
--
Matthieu Baerts (NGI0) <matttbe@kernel.org>
Hi Matthieu,
Thank you for your modifications, that's great!
Our CI did some validations and here is its report:
- KVM Validation: normal (except selftest_mptcp_join): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Success! ✅
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Perf: Unstable: 1 failed test(s): error:sched-weak-secondary ⚠️
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/41489872178
Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/b0837827f3d4
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1199267
If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:
$ cd [kernel source code]
$ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
--pull always mptcp/mptcp-upstream-virtme-docker:latest \
auto-normal
For more details:
https://github.com/multipath-tcp/mptcp-upstream-virtme-docker
Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)
Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
Hello,
On 02/11/2026 17:45, Matthieu Baerts (NGI0) wrote:
> Since commit d09c2aa3109f ("bpf: Track borrowed iterator results by
> default"), the verifier ties a struct pointer returned by an iterator's
> next kfunc to the current element by default: it is invalidated by the
> following "next" call, and by "destroy".
>
> That breaks the MPTCP BPF schedulers tests, keeping a subflow after
> advancing the iterator: bpf_rr keeps the first subflow, and bpf_burst
> keeps the "best" ones to use them after the loop. Both are now rejected
> at load time:
>
> R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_
> (...)
> # test_rr:FAIL:open_and_load: rr unexpected error: -13
>
> The returned subflow is not tied to the iterator position: next only
> walks msk->conn_list, destroy is empty, and no per-element protection
> is dropped. In fact, the subflow is still valid thanks to the held msk
> lock. Then declare it with KF_ITER_RET_INDEPENDENT.
It looks like it fixes the issue reported by the CI. I suggest applying
it now, not to impact other devs. I can always change this later if needed.
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
Hi Matt,
On Mon, 2026-11-02 at 19:52 +0100, Matthieu Baerts wrote:
> Hello,
>
> On 02/11/2026 17:45, Matthieu Baerts (NGI0) wrote:
> > Since commit d09c2aa3109f ("bpf: Track borrowed iterator results by
> > default"), the verifier ties a struct pointer returned by an
> > iterator's
> > next kfunc to the current element by default: it is invalidated by
> > the
> > following "next" call, and by "destroy".
> >
> > That breaks the MPTCP BPF schedulers tests, keeping a subflow after
> > advancing the iterator: bpf_rr keeps the first subflow, and
> > bpf_burst
> > keeps the "best" ones to use them after the loop. Both are now
> > rejected
> > at load time:
> >
> > R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_
> > (...)
> > # test_rr:FAIL:open_and_load: rr unexpected error: -13
> >
> > The returned subflow is not tied to the iterator position: next
> > only
> > walks msk->conn_list, destroy is empty, and no per-element
> > protection
> > is dropped. In fact, the subflow is still valid thanks to the held
> > msk
> > lock. Then declare it with KF_ITER_RET_INDEPENDENT.
>
> It looks like it fixes the issue reported by the CI. I suggest
> applying
> it now, not to impact other devs. I can always change this later if
> needed.
I've just reproduced the issue and confirmed that this patch fixes it.
Please apply this patch.
Reviewed-by: Geliang Tang <geliang@kernel.org>
Thanks,
-Geliang
>
> Cheers,
> Matt
© 2016 - 2026 Red Hat, Inc.