[ Sasha's backport helper bot ]
Hi,
✅ All tests passed successfully. No issues detected. No action required from the submitter.
The upstream commit SHA1 provided is correct: f8a1d9b18c5efc76784f5a326e905f641f839894
WARNING: Author mismatch between patch and upstream commit: Backport author: Matthieu Baerts (NGI0) matttbe@kernel.org Commit author: Paolo Abeni pabeni@redhat.com
Status in newer kernel trees: 6.15.y | Not found 6.12.y | Not found
Note: The patch differs from the upstream commit: --- 1: f8a1d9b18c5e ! 1: 6ccd3bb7c647 mptcp: make fallback action and fallback decision atomic @@ Metadata ## Commit message ## mptcp: make fallback action and fallback decision atomic
+ commit f8a1d9b18c5efc76784f5a326e905f641f839894 upstream. + Syzkaller reported the following splat:
WARNING: CPU: 1 PID: 7704 at net/mptcp/protocol.h:1223 __mptcp_do_fallback net/mptcp/protocol.h:1223 [inline] @@ Commit message Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Link: https://patch.msgid.link/20250714-net-mptcp-fallback-races-v1-1-391aff963322... Signed-off-by: Jakub Kicinski kuba@kernel.org + [ Conflicts in protocol.h, because commit 6ebf6f90ab4a ("mptcp: add + mptcpi_subflows_total counter") is not in this version, and this + causes conflicts in the context. Commit 65b02260a0e0 ("mptcp: export + mptcp_subflow_early_fallback()") is also not in this version, and + moves code from protocol.c to protocol.h, but the modification can + still apply there. ] + Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org
## net/mptcp/options.c ## @@ net/mptcp/options.c: static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, @@ net/mptcp/protocol.c: static void __mptcp_retrans(struct sock *sk) release_sock(ssk); } @@ net/mptcp/protocol.c: static void __mptcp_init_sock(struct sock *sk) - msk->last_ack_recv = tcp_jiffies32; + msk->subflow_id = 1;
mptcp_pm_data_init(msk); + spin_lock_init(&msk->fallback_lock); @@ net/mptcp/protocol.c: bool mptcp_finish_join(struct sock *ssk) mptcp_propagate_sndbuf(parent, ssk); return true; } +@@ net/mptcp/protocol.c: static void mptcp_subflow_early_fallback(struct mptcp_sock *msk, + struct mptcp_subflow_context *subflow) + { + subflow->request_mptcp = 0; +- __mptcp_do_fallback(msk); ++ WARN_ON_ONCE(!__mptcp_try_fallback(msk)); + } + + static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
## net/mptcp/protocol.h ## @@ net/mptcp/protocol.h: struct mptcp_sock { @@ net/mptcp/protocol.h: static inline bool mptcp_check_fallback(const struct sock -static inline void __mptcp_do_fallback(struct mptcp_sock *msk) +static inline bool __mptcp_try_fallback(struct mptcp_sock *msk) { - if (__mptcp_check_fallback(msk)) { + if (test_bit(MPTCP_FALLBACK_DONE, &msk->flags)) { pr_debug("TCP fallback already done (msk=%p)\n", msk); - return; + return true; @@ net/mptcp/protocol.h: static inline bool mptcp_check_fallback(const struct sock + return true; }
- static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk) -@@ net/mptcp/protocol.h: static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk) - TCPF_SYN_RECV | TCPF_LISTEN)); - } - -static inline void mptcp_do_fallback(struct sock *ssk) +static inline bool mptcp_try_fallback(struct sock *ssk) { @@ net/mptcp/protocol.h: static inline void mptcp_do_fallback(struct sock *ssk) }
#define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)\n", __func__, a) -@@ net/mptcp/protocol.h: static inline void mptcp_subflow_early_fallback(struct mptcp_sock *msk, - { - pr_fallback(msk); - subflow->request_mptcp = 0; -- __mptcp_do_fallback(msk); -+ WARN_ON_ONCE(!__mptcp_try_fallback(msk)); - } - - static inline bool mptcp_check_infinite_map(struct sk_buff *skb)
## net/mptcp/subflow.c ## @@ net/mptcp/subflow.c: static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) @@ net/mptcp/subflow.c: static bool subflow_check_data_avail(struct sock *ssk) * subflow_error_report() will introduce the appropriate barriers */ @@ net/mptcp/subflow.c: static bool subflow_check_data_avail(struct sock *ssk) - WRITE_ONCE(subflow->data_avail, false); + WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA); return false; } - @@ net/mptcp/subflow.c: static bool subflow_check_data_avail(struct sock *ssk) }
skb = skb_peek(&ssk->sk_receive_queue); -@@ net/mptcp/subflow.c: int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local, +@@ net/mptcp/subflow.c: int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc, /* discard the subflow socket */ mptcp_sock_graft(ssk, sk->sk_socket); iput(SOCK_INODE(sf));
---
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | 6.6 | Success | Success |