FAILED: patch "[PATCH] mptcp: prevent race between disconnect() and rtx" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 85c580b0d8590520ae00a15c29e9fb9c99427a3e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091621-feed-gargle-2568@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 85c580b0d8590520ae00a15c29e9fb9c99427a3e Mon Sep 17 00:00:00 2001
From: Paolo Abeni <[email protected]>
Date: Tue, 8 Sep 2026 16:07:11 +0200
Subject: [PATCH] mptcp: prevent race between disconnect() and rtx
Sashiko noted that the two event can race, leading to inconsistent status. Prevent the race using the synchronous timer stop operation.
net/mptcp/protocol.c +8 -2
@@ -3588,6 +3588,7 @@ static void mptcp_destroy_common(struct mptcp_sock *msk)static int mptcp_disconnect (struct sock *sk,int flags) { +struct inet_connection_sock *icsk =inet_csk (sk);struct mptcp_sock *msk =mptcp_sk (sk);/* We are on the fastopen error path. We can't call straight into the
@@ -3600,8 +3601,13 @@ static int mptcp_disconnect(struct sock *sk, int flags)mptcp_check_listen_stop (sk);mptcp_set_state (sk,TCP_CLOSE ); -mptcp_stop_rtx_timer (sk); -mptcp_stop_tout_timer (sk); +/* The later subflow close can not kick again the tout timer, +* as the msk is already in closed status. +*/ + msk->timer_ival = icsk->icsk_rto_min; +sk_stop_timer_sync (sk, &sk->mptcp_retransmit_timer); + icsk->icsk_mtup.probe_timestamp =0 ; +sk_stop_timer_sync (sk, &icsk->mptcp_tout_timer);mptcp_pm_connection_closed (msk);
Sasha Levin
maintainerPATCH 1/2 tcp: introduce icsk->icsk_keepalive_timer
From: Eric Dumazet <[email protected]>
[ Upstream commit 08dfe370239e53494453cee1e2ded2cdaa1efd12 ]
sk->sk_timer has been used for TCP keepalives.
Keepalive timers are not in fast path, we want to use sk->sk_timer storage for retransmit timers, for better cache locality.
Create icsk->icsk_keepalive_timer and change keepalive code to no longer use sk->sk_timer.
Added space is reclaimed in the following patch.
This includes changes to MPTCP, which was also using sk_timer.
Alias icsk->mptcp_tout_timer and icsk->icsk_keepalive_timer for inet_sk_diag_fill() sake.
[6.12 dependency adaptation for 85c580b0d859:
Keep the 6.12 from_timer(), icsk_timeout and existing inet_csk keepalive helpers. Move those helpers and the DCCP keepalive callback to the new timer as well; DCCP still shares inet_csk_init_xmit_timers() in this tree. Preserve the stable cacheline documentation format and retransmit fields.
Include only the MPTCP retransmit-timer migration from 9a5e5334adc03:
alias sk_timer as mptcp_retransmit_timer and update its initialization, callback, pending checks, reset and stop operations. TCP and DCCP keep their existing icsk_retransmit_timer.
Use the existing mptcp_pm_connection_closed() helper for close events, following 5add80bfdc46f, so the target's disconnect hunk applies unchanged. Initialize MPTCP's icsk_rto_min to the stable TCP_RTO_MIN default, since the target reads it but MPTCP does not call tcp_init_sock().
No functions are added. The synchronous-stop fix remains in the target.]
Stable-dep-of: 85c580b0d859 ("mptcp: prevent race between disconnect() and rtx")
--- .../net_cachelines/inet_connection_sock.rst | 1 + include/net/inet_connection_sock.h | 11 +++++-- include/net/sock.h | 6 +++- net/dccp/timer.c | 4 ++- net/ipv4/inet_connection_sock.c | 10 +++--- net/ipv4/inet_diag.c | 4 +-- net/ipv4/tcp_ipv4.c | 4 +-- net/ipv4/tcp_timer.c | 5 +-- net/ipv6/tcp_ipv6.c | 4 +-- net/mptcp/pm.c | 3 ++ net/mptcp/protocol.c | 33 ++++++++----------- net/mptcp/protocol.h | 2 +- .../selftests/bpf/progs/bpf_iter_tcp4.c | 4 +-- .../selftests/bpf/progs/bpf_iter_tcp6.c | 4 +-- 14 files changed, 54 insertions(+), 41 deletions(-)
Documentation/networking/net_cachelines/inet_connection_sock.rst +1 -0
@@ -14,6 +14,7 @@ struct_inet_bind2_bucket icsk_bind2_hash read_mostly - unsigned_long icsk_timeout read_mostly - inet_csk_reset_xmit_timer,tcp_connect struct_timer_list icsk_retransmit_timer read_mostly - inet_csk_reset_xmit_timer,tcp_connect struct_timer_list icsk_delack_timer read_mostly - inet_csk_reset_xmit_timer,tcp_connect +struct_timer_list icsk_keepalive_timer - - u32 icsk_rto read_write - tcp_cwnd_validate,tcp_schedule_loss_probe,tcp_connect_init,tcp_connect,tcp_write_xmit,tcp_push_one u32 icsk_rto_min - - u32 icsk_delack_max - -
include/net/inet_connection_sock.h +9 -2
@@ -62,6 +62,9 @@ struct inet_connection_sock_af_ops {* @icsk_bind2_hash: Bind node in the bhash2 table * @icsk_timeout: Timeout * @icsk_retransmit_timer: Resend (no ack) +* @icsk_delack_timer: Delayed ACK timer +* @icsk_keepalive_timer: Keepalive timer +* @mptcp_tout_timer: MPTCP timeout timer * @icsk_rto: Retransmit timeout * @icsk_pmtu_cookie Last pmtu seen by socket * @icsk_ca_ops Pluggable congestion control hook
@@ -88,8 +91,12 @@ struct inet_connection_sock {struct inet_bind_bucket *icsk_bind_hash;struct inet_bind2_bucket *icsk_bind2_hash;unsigned long icsk_timeout; -struct timer_list icsk_retransmit_timer; -struct timer_list icsk_delack_timer; +struct timer_list icsk_retransmit_timer; +struct timer_list icsk_delack_timer; +union { +struct timer_list icsk_keepalive_timer; +struct timer_list mptcp_tout_timer; + };__u32 icsk_rto;__u32 icsk_rto_min;__u32 icsk_delack_max;
include/net/sock.h +5 -1
@@ -300,6 +300,7 @@ struct sk_filter;* @sk_txrehash: enable TX hash rethink * @sk_filter: socket filtering instructions * @sk_timer: sock cleanup timer +* @mptcp_retransmit_timer: MPTCP retransmit timer * @sk_stamp: time stamp of last packet received * @sk_stamp_seq: lock for accessing sk_stamp on 32 bit architectures only * @sk_tsflags: SO_TIMESTAMPING flags
@@ -465,7 +466,10 @@ struct sock {u32 sk_dst_pending_confirm;u32 sk_pacing_status;/* see enum sk_pacing */ struct page_frag sk_frag; -struct timer_list sk_timer; +union { +struct timer_list sk_timer; +struct timer_list mptcp_retransmit_timer; + };unsigned long sk_pacing_rate;/* bytes per second */ atomic_t sk_zckey;
net/dccp/timer.c +3 -1
@@ -160,7 +160,9 @@ static void dccp_write_timer(struct timer_list *t)static void dccp_keepalive_timer (struct timer_list *t) { -struct sock *sk =from_timer (sk, t, sk_timer); +struct inet_connection_sock *icsk = +from_timer (icsk, t, icsk_keepalive_timer); +struct sock *sk = &icsk->icsk_inet.sk;pr_err ("dccp should not use a keepalive timer !\n" );sock_put (sk);
net/ipv4/inet_connection_sock.c +5 -5
@@ -750,7 +750,7 @@ void inet_csk_init_xmit_timers(struct sock *sk,timer_setup (&icsk->icsk_retransmit_timer, retransmit_handler,0 );timer_setup (&icsk->icsk_delack_timer, delack_handler,0 ); -timer_setup (&sk->sk_timer, keepalive_handler,0 ); +timer_setup (&icsk->icsk_keepalive_timer, keepalive_handler,0 ); icsk->icsk_pending = icsk->icsk_ack.pending =0 ; }EXPORT_SYMBOL (inet_csk_init_xmit_timers);
@@ -763,7 +763,7 @@ void inet_csk_clear_xmit_timers(struct sock *sk)sk_stop_timer (sk, &icsk->icsk_retransmit_timer);sk_stop_timer (sk, &icsk->icsk_delack_timer); -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &icsk->icsk_keepalive_timer); }EXPORT_SYMBOL (inet_csk_clear_xmit_timers);
@@ -778,18 +778,18 @@ void inet_csk_clear_xmit_timers_sync(struct sock *sk)sk_stop_timer_sync (sk, &icsk->icsk_retransmit_timer);sk_stop_timer_sync (sk, &icsk->icsk_delack_timer); -sk_stop_timer_sync (sk, &sk->sk_timer); +sk_stop_timer_sync (sk, &icsk->icsk_keepalive_timer); }void inet_csk_delete_keepalive_timer (struct sock *sk) { -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->icsk_keepalive_timer); }EXPORT_SYMBOL (inet_csk_delete_keepalive_timer);void inet_csk_reset_keepalive_timer (struct sock *sk,unsigned long len) { -sk_reset_timer (sk, &sk->sk_timer, jiffies + len); +sk_reset_timer (sk, &inet_csk (sk)->icsk_keepalive_timer, jiffies + len); }EXPORT_SYMBOL (inet_csk_reset_keepalive_timer);
net/ipv4/inet_diag.c +2 -2
@@ -319,11 +319,11 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, r->idiag_retrans = icsk->icsk_probes_out; r->idiag_expires =jiffies_delta_to_msecs (icsk->icsk_timeout - jiffies); - }else if (timer_pending (&sk->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { r->idiag_timer =2 ; r->idiag_retrans = icsk->icsk_probes_out; r->idiag_expires = -jiffies_delta_to_msecs (sk->sk_timer.expires - jiffies); +jiffies_delta_to_msecs (icsk->icsk_keepalive_timer.expires - jiffies); }if ((ext & (1 << (INET_DIAG_INFO -1 ))) && handler->idiag_info_size) {
net/ipv4/tcp_ipv4.c +2 -2
@@ -2919,9 +2919,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i) }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_timeout; - }else if (timer_pending (&sk->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sk->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires = jiffies;
net/ipv4/tcp_timer.c +3 -2
@@ -755,8 +755,9 @@ EXPORT_IPV6_MOD_GPL(tcp_set_keepalive);static void tcp_keepalive_timer (struct timer_list *t) { -struct sock *sk =from_timer (sk, t, sk_timer); -struct inet_connection_sock *icsk =inet_csk (sk); +struct inet_connection_sock *icsk = +from_timer (icsk, t, icsk_keepalive_timer); +struct sock *sk = &icsk->icsk_inet.sk;struct tcp_sock *tp =tcp_sk (sk);u32 elapsed;
net/ipv6/tcp_ipv6.c +2 -2
@@ -2177,9 +2177,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_timeout; - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires = jiffies;
net/mptcp/pm.c +3 -0
@@ -154,6 +154,9 @@ void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk)void mptcp_pm_connection_closed (struct mptcp_sock *msk) {pr_debug ("msk=%p\n" , msk); + +if (msk->token) +mptcp_event (MPTCP_EVENT_CLOSED , msk,NULL ,GFP_KERNEL ); }void mptcp_pm_subflow_established (struct mptcp_sock *msk)
net/mptcp/protocol.c +14 -19
@@ -414,9 +414,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk_buff *skb)static void mptcp_stop_rtx_timer (struct sock *sk) { -struct inet_connection_sock *icsk =inet_csk (sk); - -sk_stop_timer (sk, &icsk->icsk_retransmit_timer); +sk_stop_timer (sk, &sk->mptcp_retransmit_timer);mptcp_sk (sk)->timer_ival =0 ; }
@@ -973,12 +971,11 @@ static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_liststatic bool mptcp_rtx_timer_pending (struct sock *sk) { -return timer_pending (&inet_csk (sk)->icsk_retransmit_timer); +return timer_pending (&sk->mptcp_retransmit_timer); }static void mptcp_reset_rtx_timer (struct sock *sk) { -struct inet_connection_sock *icsk =inet_csk (sk);unsigned long tout;/* prevent rescheduling on close */
@@ -986,7 +983,7 @@ static void mptcp_reset_rtx_timer(struct sock *sk)return ; tout =mptcp_sk (sk)->timer_ival; -sk_reset_timer (sk, &icsk->icsk_retransmit_timer, jiffies + tout); +sk_reset_timer (sk, &sk->mptcp_retransmit_timer, jiffies + tout); }bool mptcp_schedule_work (struct sock *sk)
@@ -2390,9 +2387,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,static void mptcp_retransmit_timer (struct timer_list *t) { -struct inet_connection_sock *icsk =from_timer (icsk, t, - icsk_retransmit_timer); -struct sock *sk = &icsk->icsk_inet.sk; +struct sock *sk =from_timer (sk, t, mptcp_retransmit_timer);struct mptcp_sock *msk =mptcp_sk (sk);bh_lock_sock (sk);
@@ -2410,7 +2405,9 @@ static void mptcp_retransmit_timer(struct timer_list *t)static void mptcp_tout_timer (struct timer_list *t) { -struct sock *sk =from_timer (sk, t, sk_timer); +struct inet_connection_sock *icsk = +from_timer (icsk, t, mptcp_tout_timer); +struct sock *sk = &icsk->icsk_inet.sk;mptcp_schedule_work (sk);sock_put (sk);
@@ -2853,7 +2850,7 @@ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)*/ timeout =inet_csk (sk)->icsk_mtup.probe_timestamp ? close_timeout : fail_tout; -sk_reset_timer (sk, &sk->sk_timer, timeout); +sk_reset_timer (sk, &inet_csk (sk)->mptcp_tout_timer, timeout); }static void mptcp_mp_fail_no_response (struct mptcp_sock *msk)
@@ -2969,6 +2966,7 @@ static void __mptcp_init_sock(struct sock *sk) msk->first_pending =NULL ;WRITE_ONCE (msk->rmem_fwd_alloc,0 );WRITE_ONCE (msk->rmem_released,0 ); +inet_csk (sk)->icsk_rto_min =TCP_RTO_MIN ; msk->timer_ival =TCP_RTO_MIN ; msk->scaling_ratio =TCP_DEFAULT_SCALING_RATIO ;
@@ -2986,9 +2984,8 @@ static void __mptcp_init_sock(struct sock *sk)mptcp_pm_data_init (msk);spin_lock_init (&msk->fallback_lock); -/* re-use the csk retrans timer for MPTCP-level retrans */ -timer_setup (&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer,0 ); -timer_setup (&sk->sk_timer, mptcp_tout_timer,0 ); +timer_setup (&sk->mptcp_retransmit_timer, mptcp_retransmit_timer,0 ); +timer_setup (&msk->sk.mptcp_tout_timer, mptcp_tout_timer,0 ); }static void mptcp_ca_reset (struct sock *sk)
@@ -3190,7 +3187,7 @@ static void __mptcp_destroy_sock(struct sock *sk)might_sleep ();mptcp_stop_rtx_timer (sk); -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->mptcp_tout_timer); msk->pm.status =0 ;mptcp_release_sched (msk);
@@ -3295,8 +3292,7 @@ bool __mptcp_close(struct sock *sk, long timeout)sock_hold (sk);pr_debug ("msk=%p state=%d\n" , sk, sk->sk_state); -if (msk->token) -mptcp_event (MPTCP_EVENT_CLOSED , msk,NULL ,GFP_KERNEL ); +mptcp_pm_connection_closed (msk);if (sk->sk_state ==TCP_CLOSE ) {__mptcp_destroy_sock (sk);
@@ -3362,8 +3358,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)mptcp_stop_rtx_timer (sk);mptcp_stop_tout_timer (sk); -if (msk->token) -mptcp_event (MPTCP_EVENT_CLOSED , msk,NULL ,GFP_KERNEL ); +mptcp_pm_connection_closed (msk);/* msk->subflow is still intact, the following will not free the first * subflow
net/mptcp/protocol.h +1 -1
@@ -844,7 +844,7 @@ static inline void mptcp_stop_tout_timer(struct sock *sk)if (!inet_csk (sk)->icsk_mtup.probe_timestamp)return ; -sk_stop_timer (sk, &sk->sk_timer); +sk_stop_timer (sk, &inet_csk (sk)->mptcp_tout_timer);inet_csk (sk)->icsk_mtup.probe_timestamp =0 ; }
tools/testing/selftests/bpf/progs/bpf_iter_tcp4.c +2 -2
@@ -103,9 +103,9 @@ static int dump_tcp_sock(struct seq_file *seq, struct tcp_sock *tp, }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_timeout; - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires =bpf_jiffies64 ();
tools/testing/selftests/bpf/progs/bpf_iter_tcp6.c +2 -2
@@ -103,9 +103,9 @@ static int dump_tcp6_sock(struct seq_file *seq, struct tcp6_sock *tp, }else if (icsk->icsk_pending ==ICSK_TIME_PROBE0 ) { timer_active =4 ; timer_expires = icsk->icsk_timeout; - }else if (timer_pending (&sp->sk_timer)) { + }else if (timer_pending (&icsk->icsk_keepalive_timer)) { timer_active =2 ; - timer_expires = sp->sk_timer.expires; + timer_expires = icsk->icsk_keepalive_timer.expires; }else { timer_active =0 ; timer_expires =bpf_jiffies64 ();
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 mptcp: prevent race between disconnect() and rtx
From: Paolo Abeni <[email protected]>
[ Upstream commit 85c580b0d8590520ae00a15c29e9fb9c99427a3e ]
Sashiko noted that the two event can race, leading to inconsistent status. Prevent the race using the synchronous timer stop operation.
--- net/mptcp/protocol.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/mptcp/protocol.c +8 -2
@@ -3343,6 +3343,7 @@ static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)static int mptcp_disconnect (struct sock *sk,int flags) { +struct inet_connection_sock *icsk =inet_csk (sk);struct mptcp_sock *msk =mptcp_sk (sk);/* We are on the fastopen error path. We can't call straight into the
@@ -3355,8 +3356,13 @@ static int mptcp_disconnect(struct sock *sk, int flags)mptcp_check_listen_stop (sk);mptcp_set_state (sk,TCP_CLOSE ); -mptcp_stop_rtx_timer (sk); -mptcp_stop_tout_timer (sk); +/* The later subflow close can not kick again the tout timer, +* as the msk is already in closed status. +*/ + msk->timer_ival = icsk->icsk_rto_min; +sk_stop_timer_sync (sk, &sk->mptcp_retransmit_timer); + icsk->icsk_mtup.probe_timestamp =0 ; +sk_stop_timer_sync (sk, &icsk->mptcp_tout_timer);mptcp_pm_connection_closed (msk);
Signature · 1 line
2.53.0