Re: [PATCH net] mptcp: fix use-after-free of the subflow context on the delegated list
Matthieu Baerts <[email protected]>
| Newsgroups | dev.linux.lists.mptcp,org.kernel.vger.netdev |
|---|---|
| Organization | NGI0 Core |
| Message-ID | <[email protected]> |
Hi Hyunwoo, On 19/08/2026 12:13, Hyunwoo Kim wrote: > mptcp_subflow_delegate() links the subflow context into a per-CPU napi > list and takes a reference on the subflow socket. The context is a > separate allocation, reached through icsk_ulp_data, and the list holds > no reference to it. > > inet_csk_destroy_sock() runs sk_prot->destroy() regardless of the > outstanding references. That path ends in tcp_cleanup_ulp(), which calls > subflow_ulp_release(). subflow_ulp_release() frees the context with > kfree_rcu() but does not remove it from the list. Once the grace period > elapses and the context is actually freed, the next mptcp_napi_poll() > dequeues that entry and mptcp_subflow_delegated_next() writes to the > freed context with list_del_init(). That is the use-after-free. > > The freeing path cannot dequeue the entry itself: the list is per-CPU > and only the CPU that queued the subflow may touch it, as > tcp_release_cb_override() already notes. > > Delay the free instead. Add MPTCP_DELEGATE_DEAD. > mptcp_subflow_free_ctx() sets it and frees the context only if the > subflow is not scheduled, while mptcp_napi_poll() frees it if the dead > bit is set when it clears the scheduled bit. Either > mptcp_subflow_free_ctx() gets there first, sees the scheduled bit and > leaves the free to mptcp_napi_poll(), or mptcp_napi_poll() gets there > first, does not see the dead bit and mptcp_subflow_free_ctx() does the > free. > > Also skip mptcp_subflow_process_delegated() once the dead bit is set. > subflow_ulp_release() has already dropped the msk reference by then, so > the pending actions must not run. > > Finally, move delegated_status out of struct_group(reset). > mptcp_subflow_ctx_reset() clears that group on disconnect, and clearing > the scheduled bit while the entry is still queued would let > mptcp_subflow_free_ctx() free a context the napi list still points to. > delegated_node is already outside the group. Thank you for looking at this. Do you have more context about how the bug was discovered? Do you have a reproducer and/or a KASAN calltrace or similar? Having this would help the reviewers. Cheers, Matt -- Sponsored by the NGI0 Core fund.