Commit e596212e authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-fixes'

Mat Martineau says:

====================
mptcp: Fixes for v5.13

Here are two MPTCP fixes from Paolo.

Patch 1 fixes some possible connect-time race conditions with
MPTCP-level connection state changes.

Patch 2 deletes a duplicate function declaration.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3ddd6e2f 597dbae7
...@@ -2946,6 +2946,11 @@ static void mptcp_release_cb(struct sock *sk) ...@@ -2946,6 +2946,11 @@ static void mptcp_release_cb(struct sock *sk)
spin_lock_bh(&sk->sk_lock.slock); spin_lock_bh(&sk->sk_lock.slock);
} }
/* be sure to set the current sk state before tacking actions
* depending on sk_state
*/
if (test_and_clear_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->flags))
__mptcp_set_connected(sk);
if (test_and_clear_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags)) if (test_and_clear_bit(MPTCP_CLEAN_UNA, &mptcp_sk(sk)->flags))
__mptcp_clean_una_wakeup(sk); __mptcp_clean_una_wakeup(sk);
if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags)) if (test_and_clear_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->flags))
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
#define MPTCP_ERROR_REPORT 8 #define MPTCP_ERROR_REPORT 8
#define MPTCP_RETRANSMIT 9 #define MPTCP_RETRANSMIT 9
#define MPTCP_WORK_SYNC_SETSOCKOPT 10 #define MPTCP_WORK_SYNC_SETSOCKOPT 10
#define MPTCP_CONNECTED 11
static inline bool before64(__u64 seq1, __u64 seq2) static inline bool before64(__u64 seq1, __u64 seq2)
{ {
...@@ -579,6 +580,7 @@ void mptcp_get_options(const struct sk_buff *skb, ...@@ -579,6 +580,7 @@ void mptcp_get_options(const struct sk_buff *skb,
struct mptcp_options_received *mp_opt); struct mptcp_options_received *mp_opt);
void mptcp_finish_connect(struct sock *sk); void mptcp_finish_connect(struct sock *sk);
void __mptcp_set_connected(struct sock *sk);
static inline bool mptcp_is_fully_established(struct sock *sk) static inline bool mptcp_is_fully_established(struct sock *sk)
{ {
return inet_sk_state_load(sk) == TCP_ESTABLISHED && return inet_sk_state_load(sk) == TCP_ESTABLISHED &&
...@@ -760,9 +762,6 @@ unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk); ...@@ -760,9 +762,6 @@ unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk); unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk);
unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk); unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk);
int mptcp_setsockopt(struct sock *sk, int level, int optname,
sockptr_t optval, unsigned int optlen);
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk); void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk);
void mptcp_sockopt_sync_all(struct mptcp_sock *msk); void mptcp_sockopt_sync_all(struct mptcp_sock *msk);
......
...@@ -371,6 +371,24 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc ...@@ -371,6 +371,24 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc
return inet_sk(sk)->inet_dport != inet_sk((struct sock *)msk)->inet_dport; return inet_sk(sk)->inet_dport != inet_sk((struct sock *)msk)->inet_dport;
} }
void __mptcp_set_connected(struct sock *sk)
{
if (sk->sk_state == TCP_SYN_SENT) {
inet_sk_state_store(sk, TCP_ESTABLISHED);
sk->sk_state_change(sk);
}
}
static void mptcp_set_connected(struct sock *sk)
{
mptcp_data_lock(sk);
if (!sock_owned_by_user(sk))
__mptcp_set_connected(sk);
else
set_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->flags);
mptcp_data_unlock(sk);
}
static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
{ {
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
...@@ -379,10 +397,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -379,10 +397,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
subflow->icsk_af_ops->sk_rx_dst_set(sk, skb); subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
if (inet_sk_state_load(parent) == TCP_SYN_SENT) {
inet_sk_state_store(parent, TCP_ESTABLISHED);
parent->sk_state_change(parent);
}
/* be sure no special action on any packet other than syn-ack */ /* be sure no special action on any packet other than syn-ack */
if (subflow->conn_finished) if (subflow->conn_finished)
...@@ -411,6 +425,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -411,6 +425,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
subflow->remote_key); subflow->remote_key);
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK); MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK);
mptcp_finish_connect(sk); mptcp_finish_connect(sk);
mptcp_set_connected(parent);
} else if (subflow->request_join) { } else if (subflow->request_join) {
u8 hmac[SHA256_DIGEST_SIZE]; u8 hmac[SHA256_DIGEST_SIZE];
...@@ -451,6 +466,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) ...@@ -451,6 +466,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
} else if (mptcp_check_fallback(sk)) { } else if (mptcp_check_fallback(sk)) {
fallback: fallback:
mptcp_rcv_space_init(mptcp_sk(parent), sk); mptcp_rcv_space_init(mptcp_sk(parent), sk);
mptcp_set_connected(parent);
} }
return; return;
...@@ -558,6 +574,7 @@ static void mptcp_sock_destruct(struct sock *sk) ...@@ -558,6 +574,7 @@ static void mptcp_sock_destruct(struct sock *sk)
static void mptcp_force_close(struct sock *sk) static void mptcp_force_close(struct sock *sk)
{ {
/* the msk is not yet exposed to user-space */
inet_sk_state_store(sk, TCP_CLOSE); inet_sk_state_store(sk, TCP_CLOSE);
sk_common_release(sk); sk_common_release(sk);
} }
...@@ -1474,10 +1491,7 @@ static void subflow_state_change(struct sock *sk) ...@@ -1474,10 +1491,7 @@ static void subflow_state_change(struct sock *sk)
mptcp_rcv_space_init(mptcp_sk(parent), sk); mptcp_rcv_space_init(mptcp_sk(parent), sk);
pr_fallback(mptcp_sk(parent)); pr_fallback(mptcp_sk(parent));
subflow->conn_finished = 1; subflow->conn_finished = 1;
if (inet_sk_state_load(parent) == TCP_SYN_SENT) { mptcp_set_connected(parent);
inet_sk_state_store(parent, TCP_ESTABLISHED);
parent->sk_state_change(parent);
}
} }
/* as recvmsg() does not acquire the subflow socket for ssk selection /* as recvmsg() does not acquire the subflow socket for ssk selection
......
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