Skip to content

Commit fe1fd0c

Browse files
committed
Merge branch 'mptcp-fixes-for-6-1'
Mat Martineau says: ==================== mptcp: Fixes for 6.1 Patch 1 fixes an issue with assigning subflow IDs in cases where an incoming MP_JOIN is processed before accept() completes on the MPTCP socket. Patches 2 and 3 fix a deadlock issue with fastopen code (new for 6.1) at connection time. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 4a4b684 + fa9e574 commit fe1fd0c

File tree

3 files changed

+113
-81
lines changed

3 files changed

+113
-81
lines changed

net/mptcp/protocol.c

Lines changed: 102 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,37 @@ static void mptcp_set_nospace(struct sock *sk)
16731673
set_bit(MPTCP_NOSPACE, &mptcp_sk(sk)->flags);
16741674
}
16751675

1676+
static int mptcp_sendmsg_fastopen(struct sock *sk, struct sock *ssk, struct msghdr *msg,
1677+
size_t len, int *copied_syn)
1678+
{
1679+
unsigned int saved_flags = msg->msg_flags;
1680+
struct mptcp_sock *msk = mptcp_sk(sk);
1681+
int ret;
1682+
1683+
lock_sock(ssk);
1684+
msg->msg_flags |= MSG_DONTWAIT;
1685+
msk->connect_flags = O_NONBLOCK;
1686+
msk->is_sendmsg = 1;
1687+
ret = tcp_sendmsg_fastopen(ssk, msg, copied_syn, len, NULL);
1688+
msk->is_sendmsg = 0;
1689+
msg->msg_flags = saved_flags;
1690+
release_sock(ssk);
1691+
1692+
/* do the blocking bits of inet_stream_connect outside the ssk socket lock */
1693+
if (ret == -EINPROGRESS && !(msg->msg_flags & MSG_DONTWAIT)) {
1694+
ret = __inet_stream_connect(sk->sk_socket, msg->msg_name,
1695+
msg->msg_namelen, msg->msg_flags, 1);
1696+
1697+
/* Keep the same behaviour of plain TCP: zero the copied bytes in
1698+
* case of any error, except timeout or signal
1699+
*/
1700+
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
1701+
*copied_syn = 0;
1702+
}
1703+
1704+
return ret;
1705+
}
1706+
16761707
static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
16771708
{
16781709
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1693,23 +1724,14 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
16931724

16941725
ssock = __mptcp_nmpc_socket(msk);
16951726
if (unlikely(ssock && inet_sk(ssock->sk)->defer_connect)) {
1696-
struct sock *ssk = ssock->sk;
16971727
int copied_syn = 0;
16981728

1699-
lock_sock(ssk);
1700-
1701-
ret = tcp_sendmsg_fastopen(ssk, msg, &copied_syn, len, NULL);
1729+
ret = mptcp_sendmsg_fastopen(sk, ssock->sk, msg, len, &copied_syn);
17021730
copied += copied_syn;
1703-
if (ret == -EINPROGRESS && copied_syn > 0) {
1704-
/* reflect the new state on the MPTCP socket */
1705-
inet_sk_state_store(sk, inet_sk_state_load(ssk));
1706-
release_sock(ssk);
1731+
if (ret == -EINPROGRESS && copied_syn > 0)
17071732
goto out;
1708-
} else if (ret) {
1709-
release_sock(ssk);
1733+
else if (ret)
17101734
goto do_error;
1711-
}
1712-
release_sock(ssk);
17131735
}
17141736

17151737
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
@@ -2952,7 +2974,7 @@ static void mptcp_close(struct sock *sk, long timeout)
29522974
sock_put(sk);
29532975
}
29542976

2955-
static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
2977+
void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
29562978
{
29572979
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
29582980
const struct ipv6_pinfo *ssk6 = inet6_sk(ssk);
@@ -3507,10 +3529,73 @@ static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
35073529
return put_user(answ, (int __user *)arg);
35083530
}
35093531

3532+
static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
3533+
struct mptcp_subflow_context *subflow)
3534+
{
3535+
subflow->request_mptcp = 0;
3536+
__mptcp_do_fallback(msk);
3537+
}
3538+
3539+
static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
3540+
{
3541+
struct mptcp_subflow_context *subflow;
3542+
struct mptcp_sock *msk = mptcp_sk(sk);
3543+
struct socket *ssock;
3544+
int err = -EINVAL;
3545+
3546+
ssock = __mptcp_nmpc_socket(msk);
3547+
if (!ssock)
3548+
return -EINVAL;
3549+
3550+
mptcp_token_destroy(msk);
3551+
inet_sk_state_store(sk, TCP_SYN_SENT);
3552+
subflow = mptcp_subflow_ctx(ssock->sk);
3553+
#ifdef CONFIG_TCP_MD5SIG
3554+
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
3555+
* TCP option space.
3556+
*/
3557+
if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
3558+
mptcp_subflow_early_fallback(msk, subflow);
3559+
#endif
3560+
if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk)) {
3561+
MPTCP_INC_STATS(sock_net(ssock->sk), MPTCP_MIB_TOKENFALLBACKINIT);
3562+
mptcp_subflow_early_fallback(msk, subflow);
3563+
}
3564+
if (likely(!__mptcp_check_fallback(msk)))
3565+
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE);
3566+
3567+
/* if reaching here via the fastopen/sendmsg path, the caller already
3568+
* acquired the subflow socket lock, too.
3569+
*/
3570+
if (msk->is_sendmsg)
3571+
err = __inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags, 1);
3572+
else
3573+
err = inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags);
3574+
inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
3575+
3576+
/* on successful connect, the msk state will be moved to established by
3577+
* subflow_finish_connect()
3578+
*/
3579+
if (unlikely(err && err != -EINPROGRESS)) {
3580+
inet_sk_state_store(sk, inet_sk_state_load(ssock->sk));
3581+
return err;
3582+
}
3583+
3584+
mptcp_copy_inaddrs(sk, ssock->sk);
3585+
3586+
/* unblocking connect, mptcp-level inet_stream_connect will error out
3587+
* without changing the socket state, update it here.
3588+
*/
3589+
if (err == -EINPROGRESS)
3590+
sk->sk_socket->state = ssock->state;
3591+
return err;
3592+
}
3593+
35103594
static struct proto mptcp_prot = {
35113595
.name = "MPTCP",
35123596
.owner = THIS_MODULE,
35133597
.init = mptcp_init_sock,
3598+
.connect = mptcp_connect,
35143599
.disconnect = mptcp_disconnect,
35153600
.close = mptcp_close,
35163601
.accept = mptcp_accept,
@@ -3562,78 +3647,16 @@ static int mptcp_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
35623647
return err;
35633648
}
35643649

3565-
static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
3566-
struct mptcp_subflow_context *subflow)
3567-
{
3568-
subflow->request_mptcp = 0;
3569-
__mptcp_do_fallback(msk);
3570-
}
3571-
35723650
static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
35733651
int addr_len, int flags)
35743652
{
3575-
struct mptcp_sock *msk = mptcp_sk(sock->sk);
3576-
struct mptcp_subflow_context *subflow;
3577-
struct socket *ssock;
3578-
int err = -EINVAL;
3653+
int ret;
35793654

35803655
lock_sock(sock->sk);
3581-
if (uaddr) {
3582-
if (addr_len < sizeof(uaddr->sa_family))
3583-
goto unlock;
3584-
3585-
if (uaddr->sa_family == AF_UNSPEC) {
3586-
err = mptcp_disconnect(sock->sk, flags);
3587-
sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
3588-
goto unlock;
3589-
}
3590-
}
3591-
3592-
if (sock->state != SS_UNCONNECTED && msk->subflow) {
3593-
/* pending connection or invalid state, let existing subflow
3594-
* cope with that
3595-
*/
3596-
ssock = msk->subflow;
3597-
goto do_connect;
3598-
}
3599-
3600-
ssock = __mptcp_nmpc_socket(msk);
3601-
if (!ssock)
3602-
goto unlock;
3603-
3604-
mptcp_token_destroy(msk);
3605-
inet_sk_state_store(sock->sk, TCP_SYN_SENT);
3606-
subflow = mptcp_subflow_ctx(ssock->sk);
3607-
#ifdef CONFIG_TCP_MD5SIG
3608-
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
3609-
* TCP option space.
3610-
*/
3611-
if (rcu_access_pointer(tcp_sk(ssock->sk)->md5sig_info))
3612-
mptcp_subflow_early_fallback(msk, subflow);
3613-
#endif
3614-
if (subflow->request_mptcp && mptcp_token_new_connect(ssock->sk)) {
3615-
MPTCP_INC_STATS(sock_net(ssock->sk), MPTCP_MIB_TOKENFALLBACKINIT);
3616-
mptcp_subflow_early_fallback(msk, subflow);
3617-
}
3618-
if (likely(!__mptcp_check_fallback(msk)))
3619-
MPTCP_INC_STATS(sock_net(sock->sk), MPTCP_MIB_MPCAPABLEACTIVE);
3620-
3621-
do_connect:
3622-
err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
3623-
inet_sk(sock->sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
3624-
sock->state = ssock->state;
3625-
3626-
/* on successful connect, the msk state will be moved to established by
3627-
* subflow_finish_connect()
3628-
*/
3629-
if (!err || err == -EINPROGRESS)
3630-
mptcp_copy_inaddrs(sock->sk, ssock->sk);
3631-
else
3632-
inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
3633-
3634-
unlock:
3656+
mptcp_sk(sock->sk)->connect_flags = flags;
3657+
ret = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
36353658
release_sock(sock->sk);
3636-
return err;
3659+
return ret;
36373660
}
36383661

36393662
static int mptcp_listen(struct socket *sock, int backlog)
@@ -3699,7 +3722,6 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
36993722
if (mptcp_is_fully_established(newsk))
37003723
mptcp_pm_fully_established(msk, msk->first, GFP_KERNEL);
37013724

3702-
mptcp_copy_inaddrs(newsk, msk->first);
37033725
mptcp_rcv_space_init(msk, msk->first);
37043726
mptcp_propagate_sndbuf(newsk, msk->first);
37053727

net/mptcp/protocol.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ struct mptcp_sock {
285285
u8 mpc_endpoint_id;
286286
u8 recvmsg_inq:1,
287287
cork:1,
288-
nodelay:1;
288+
nodelay:1,
289+
is_sendmsg:1;
290+
int connect_flags;
289291
struct work_struct work;
290292
struct sk_buff *ooo_last_skb;
291293
struct rb_root out_of_order_queue;
@@ -599,6 +601,7 @@ int mptcp_is_checksum_enabled(const struct net *net);
599601
int mptcp_allow_join_id0(const struct net *net);
600602
unsigned int mptcp_stale_loss_cnt(const struct net *net);
601603
int mptcp_get_pm_type(const struct net *net);
604+
void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk);
602605
void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
603606
struct mptcp_options_received *mp_opt);
604607
bool __mptcp_retransmit_pending_data(struct sock *sk);

net/mptcp/subflow.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
723723
goto dispose_child;
724724
}
725725

726+
if (new_msk)
727+
mptcp_copy_inaddrs(new_msk, child);
726728
subflow_drop_ctx(child);
727729
goto out;
728730
}
@@ -750,6 +752,11 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
750752
ctx->conn = new_msk;
751753
new_msk = NULL;
752754

755+
/* set msk addresses early to ensure mptcp_pm_get_local_id()
756+
* uses the correct data
757+
*/
758+
mptcp_copy_inaddrs(ctx->conn, child);
759+
753760
/* with OoO packets we can reach here without ingress
754761
* mpc option
755762
*/

0 commit comments

Comments
 (0)