Commit 9f05f9ad authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-fixes'

Mat Martineau says:

====================
mptcp: Fixes for mptcp cleanup/close and a selftest

Patch 1 fixes an issue with leaking subflow sockets if there's a failure
in a CGROUP_INET_SOCK_CREATE eBPF program.

Patch 2 fixes a syzkaller-detected race at MPTCP socket close.

Patch 3 is a fix for one mode of the mptcp_connect.sh selftest.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4ae97cae df9e03ae
......@@ -1240,6 +1240,9 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
info->limit > dfrag->data_len))
return 0;
if (unlikely(!__tcp_can_send(ssk)))
return -EAGAIN;
/* compute send limit */
info->mss_now = tcp_send_mss(ssk, &info->size_goal, info->flags);
copy = info->size_goal;
......@@ -1413,7 +1416,8 @@ static struct sock *mptcp_subflow_get_send(struct mptcp_sock *msk)
if (__mptcp_check_fallback(msk)) {
if (!msk->first)
return NULL;
return sk_stream_memory_free(msk->first) ? msk->first : NULL;
return __tcp_can_send(msk->first) &&
sk_stream_memory_free(msk->first) ? msk->first : NULL;
}
/* re-use last subflow, if the burst allow that */
......@@ -1564,6 +1568,8 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
if (ret <= 0) {
if (ret == -EAGAIN)
continue;
mptcp_push_release(ssk, &info);
goto out;
}
......@@ -2769,30 +2775,16 @@ static void __mptcp_wr_shutdown(struct sock *sk)
static void __mptcp_destroy_sock(struct sock *sk)
{
struct mptcp_subflow_context *subflow, *tmp;
struct mptcp_sock *msk = mptcp_sk(sk);
LIST_HEAD(conn_list);
pr_debug("msk=%p", msk);
might_sleep();
/* join list will be eventually flushed (with rst) at sock lock release time*/
list_splice_init(&msk->conn_list, &conn_list);
mptcp_stop_timer(sk);
sk_stop_timer(sk, &sk->sk_timer);
msk->pm.status = 0;
/* clears msk->subflow, allowing the following loop to close
* even the initial subflow
*/
mptcp_dispose_initial_subflow(msk);
list_for_each_entry_safe(subflow, tmp, &conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
__mptcp_close_ssk(sk, ssk, subflow, 0);
}
sk->sk_prot->destroy(sk);
WARN_ON_ONCE(msk->rmem_fwd_alloc);
......@@ -2884,24 +2876,20 @@ static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
static int mptcp_disconnect(struct sock *sk, int flags)
{
struct mptcp_subflow_context *subflow, *tmp;
struct mptcp_sock *msk = mptcp_sk(sk);
inet_sk_state_store(sk, TCP_CLOSE);
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
__mptcp_close_ssk(sk, ssk, subflow, MPTCP_CF_FASTCLOSE);
}
mptcp_stop_timer(sk);
sk_stop_timer(sk, &sk->sk_timer);
if (mptcp_sk(sk)->token)
mptcp_event(MPTCP_EVENT_CLOSED, mptcp_sk(sk), NULL, GFP_KERNEL);
mptcp_destroy_common(msk);
/* msk->subflow is still intact, the following will not free the first
* subflow
*/
mptcp_destroy_common(msk, MPTCP_CF_FASTCLOSE);
msk->last_snd = NULL;
WRITE_ONCE(msk->flags, 0);
msk->cb_flags = 0;
......@@ -3051,12 +3039,17 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
return newsk;
}
void mptcp_destroy_common(struct mptcp_sock *msk)
void mptcp_destroy_common(struct mptcp_sock *msk, unsigned int flags)
{
struct mptcp_subflow_context *subflow, *tmp;
struct sock *sk = (struct sock *)msk;
__mptcp_clear_xmit(sk);
/* join list will be eventually flushed (with rst) at sock lock release time */
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node)
__mptcp_close_ssk(sk, mptcp_subflow_tcp_sock(subflow), subflow, flags);
/* move to sk_receive_queue, sk_stream_kill_queues will purge it */
mptcp_data_lock(sk);
skb_queue_splice_tail_init(&msk->receive_queue, &sk->sk_receive_queue);
......@@ -3078,7 +3071,11 @@ static void mptcp_destroy(struct sock *sk)
{
struct mptcp_sock *msk = mptcp_sk(sk);
mptcp_destroy_common(msk);
/* clears msk->subflow, allowing the following to close
* even the initial subflow
*/
mptcp_dispose_initial_subflow(msk);
mptcp_destroy_common(msk, 0);
sk_sockets_allocated_dec(sk);
}
......
......@@ -624,16 +624,19 @@ void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
struct sockaddr_storage *addr,
unsigned short family);
static inline bool __mptcp_subflow_active(struct mptcp_subflow_context *subflow)
static inline bool __tcp_can_send(const struct sock *ssk)
{
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
/* only send if our side has not closed yet */
return ((1 << inet_sk_state_load(ssk)) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT));
}
static inline bool __mptcp_subflow_active(struct mptcp_subflow_context *subflow)
{
/* can't send if JOIN hasn't completed yet (i.e. is usable for mptcp) */
if (subflow->request_join && !subflow->fully_established)
return false;
/* only send if our side has not closed yet */
return ((1 << ssk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT));
return __tcp_can_send(mptcp_subflow_tcp_sock(subflow));
}
void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow);
......@@ -717,7 +720,7 @@ static inline void mptcp_write_space(struct sock *sk)
}
}
void mptcp_destroy_common(struct mptcp_sock *msk);
void mptcp_destroy_common(struct mptcp_sock *msk, unsigned int flags);
#define MPTCP_TOKEN_MAX_RETRIES 4
......
......@@ -621,7 +621,8 @@ static void mptcp_sock_destruct(struct sock *sk)
sock_orphan(sk);
}
mptcp_destroy_common(mptcp_sk(sk));
/* We don't need to clear msk->subflow, as it's still NULL at this point */
mptcp_destroy_common(mptcp_sk(sk), 0);
inet_sock_destruct(sk);
}
......
......@@ -553,6 +553,18 @@ static void set_nonblock(int fd, bool nonblock)
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
}
static void shut_wr(int fd)
{
/* Close our write side, ev. give some time
* for address notification and/or checking
* the current status
*/
if (cfg_wait)
usleep(cfg_wait);
shutdown(fd, SHUT_WR);
}
static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
{
struct pollfd fds = {
......@@ -630,14 +642,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
/* ... and peer also closed already */
break;
/* ... but we still receive.
* Close our write side, ev. give some time
* for address notification and/or checking
* the current status
*/
if (cfg_wait)
usleep(cfg_wait);
shutdown(peerfd, SHUT_WR);
shut_wr(peerfd);
} else {
if (errno == EINTR)
continue;
......@@ -767,7 +772,7 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd,
if (err)
return err;
shutdown(peerfd, SHUT_WR);
shut_wr(peerfd);
err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
......@@ -791,6 +796,9 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
err = do_sendfile(infd, peerfd, size);
if (err)
return err;
shut_wr(peerfd);
err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
}
......
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