Commit ecfcc6fb authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mptcp-more-fixes-for-6-3'

Matthieu Baerts says:

====================
mptcp: more fixes for 6.3

Patch 1 avoids scheduling the MPTCP worker on a closed socket on some
edge cases. It fixes issues that can be visible from v5.11.

Patch 2 makes sure the MPTCP worker doesn't try to manipulate
disconnected sockets. This is also a fix for an issue that can be
visible from v5.11.

Patch 3 fixes a NULL pointer dereference when MPTCP FastOpen is used
and an early fallback is done. A fix for v6.2.

Patch 4 improves the stability of the userspace PM selftest for a
subtest added in v6.2.
====================

Link: https://lore.kernel.org/r/20230411-upstream-net-20230411-mptcp-fixes-v1-0-ca540f3ef986@tessares.netSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 5b7be2d4 711ae788
...@@ -9,11 +9,18 @@ ...@@ -9,11 +9,18 @@
void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow, void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow,
struct request_sock *req) struct request_sock *req)
{ {
struct sock *ssk = subflow->tcp_sock; struct sock *sk, *ssk;
struct sock *sk = subflow->conn;
struct sk_buff *skb; struct sk_buff *skb;
struct tcp_sock *tp; struct tcp_sock *tp;
/* on early fallback the subflow context is deleted by
* subflow_syn_recv_sock()
*/
if (!subflow)
return;
ssk = subflow->tcp_sock;
sk = subflow->conn;
tp = tcp_sk(ssk); tp = tcp_sk(ssk);
subflow->is_mptfo = 1; subflow->is_mptfo = 1;
......
...@@ -1192,9 +1192,8 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) ...@@ -1192,9 +1192,8 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
*/ */
if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
if (mp_opt.data_fin && mp_opt.data_len == 1 && if (mp_opt.data_fin && mp_opt.data_len == 1 &&
mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) && mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64))
schedule_work(&msk->work)) mptcp_schedule_work((struct sock *)msk);
sock_hold(subflow->conn);
return true; return true;
} }
......
...@@ -2626,7 +2626,7 @@ static void mptcp_worker(struct work_struct *work) ...@@ -2626,7 +2626,7 @@ static void mptcp_worker(struct work_struct *work)
lock_sock(sk); lock_sock(sk);
state = sk->sk_state; state = sk->sk_state;
if (unlikely(state == TCP_CLOSE)) if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto unlock; goto unlock;
mptcp_check_data_fin_ack(sk); mptcp_check_data_fin_ack(sk);
......
...@@ -408,9 +408,8 @@ void mptcp_subflow_reset(struct sock *ssk) ...@@ -408,9 +408,8 @@ void mptcp_subflow_reset(struct sock *ssk)
tcp_send_active_reset(ssk, GFP_ATOMIC); tcp_send_active_reset(ssk, GFP_ATOMIC);
tcp_done(ssk); tcp_done(ssk);
if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags) && if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags))
schedule_work(&mptcp_sk(sk)->work)) mptcp_schedule_work(sk);
return; /* worker will put sk for us */
sock_put(sk); sock_put(sk);
} }
...@@ -1118,8 +1117,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk, ...@@ -1118,8 +1117,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
skb_ext_del(skb, SKB_EXT_MPTCP); skb_ext_del(skb, SKB_EXT_MPTCP);
return MAPPING_OK; return MAPPING_OK;
} else { } else {
if (updated && schedule_work(&msk->work)) if (updated)
sock_hold((struct sock *)msk); mptcp_schedule_work((struct sock *)msk);
return MAPPING_DATA_FIN; return MAPPING_DATA_FIN;
} }
...@@ -1222,17 +1221,12 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb, ...@@ -1222,17 +1221,12 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,
/* sched mptcp worker to remove the subflow if no more data is pending */ /* sched mptcp worker to remove the subflow if no more data is pending */
static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk) static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
{ {
struct sock *sk = (struct sock *)msk;
if (likely(ssk->sk_state != TCP_CLOSE)) if (likely(ssk->sk_state != TCP_CLOSE))
return; return;
if (skb_queue_empty(&ssk->sk_receive_queue) && if (skb_queue_empty(&ssk->sk_receive_queue) &&
!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) { !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
sock_hold(sk); mptcp_schedule_work((struct sock *)msk);
if (!schedule_work(&msk->work))
sock_put(sk);
}
} }
static bool subflow_can_fallback(struct mptcp_subflow_context *subflow) static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
......
...@@ -913,6 +913,7 @@ test_listener() ...@@ -913,6 +913,7 @@ test_listener()
$client4_port > /dev/null 2>&1 & $client4_port > /dev/null 2>&1 &
local listener_pid=$! local listener_pid=$!
sleep 0.5
verify_listener_events $client_evts $LISTENER_CREATED $AF_INET 10.0.2.2 $client4_port verify_listener_events $client_evts $LISTENER_CREATED $AF_INET 10.0.2.2 $client4_port
# ADD_ADDR from client to server machine reusing the subflow port # ADD_ADDR from client to server machine reusing the subflow port
...@@ -928,6 +929,7 @@ test_listener() ...@@ -928,6 +929,7 @@ test_listener()
# Delete the listener from the client ns, if one was created # Delete the listener from the client ns, if one was created
kill_wait $listener_pid kill_wait $listener_pid
sleep 0.5
verify_listener_events $client_evts $LISTENER_CLOSED $AF_INET 10.0.2.2 $client4_port verify_listener_events $client_evts $LISTENER_CLOSED $AF_INET 10.0.2.2 $client4_port
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment