Skip to content

Commit

Permalink
mptcp: avoid OOB access in setsockopt()
Browse files Browse the repository at this point in the history
We can't use tcp_set_congestion_control() on an mptcp socket, as
such function can end-up accessing a tcp-specific field -
prior_ssthresh - causing an OOB access.

To allow propagating the correct ca algo on subflow, cache the ca
name at initialization time.

Additionally avoid overriding the user-selected CA (if any) at
clone time.

Closes: #182
Fixes: aa1fbd9 ("mptcp: sockopt: add TCP_CONGESTION and TCP_INFO")
Acked-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni authored and matttbe committed May 13, 2021
1 parent f651257 commit b7abff5
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 5 deletions.
14 changes: 11 additions & 3 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -2418,13 +2418,12 @@ static int __mptcp_init_sock(struct sock *sk)
timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);

tcp_assign_congestion_control(sk);

return 0;
}

static int mptcp_init_sock(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct net *net = sock_net(sk);
int ret;

Expand All @@ -2442,6 +2441,16 @@ static int mptcp_init_sock(struct sock *sk)
if (ret)
return ret;

/* fetch the ca name; do it outside __mptcp_init_sock(), so that clone will
* propagate the correct value
*/
tcp_assign_congestion_control(sk);
strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name);

/* no need to keep a reference to the ops, the name will suffice */
tcp_cleanup_congestion_control(sk);
icsk->icsk_ca_ops = NULL;

sk_sockets_allocated_inc(sk);
sk->sk_rcvbuf = sock_net(sk)->ipv4.sysctl_tcp_rmem[1];
sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[1];
Expand Down Expand Up @@ -2616,7 +2625,6 @@ static void __mptcp_destroy_sock(struct sock *sk)
sk_stream_kill_queues(sk);
xfrm_sk_free_policy(sk);

tcp_cleanup_congestion_control(sk);
sk_refcnt_debug_release(sk);
mptcp_dispose_initial_subflow(msk);
sock_put(sk);
Expand Down
1 change: 1 addition & 0 deletions net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ struct mptcp_sock {
} rcvq_space;

u32 setsockopt_seq;
char ca_name[TCP_CA_NAME_MAX];
};

#define mptcp_lock_sock(___sk, cb) do { \
Expand Down
4 changes: 2 additions & 2 deletions net/mptcp/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
}

if (ret == 0)
tcp_set_congestion_control(sk, name, false, cap_net_admin);
strcpy(msk->ca_name, name);

release_sock(sk);
return ret;
Expand Down Expand Up @@ -705,7 +705,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
sock_valbool_flag(ssk, SOCK_DBG, sock_flag(sk, SOCK_DBG));

if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops)
tcp_set_congestion_control(ssk, inet_csk(sk)->icsk_ca_ops->name, false, true);
tcp_set_congestion_control(ssk, msk->ca_name, false, true);
}

static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
Expand Down

0 comments on commit b7abff5

Please sign in to comment.