mirror of https://gitee.com/openkylin/linux.git
mptcp: avoid OOB access in setsockopt()
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: https://github.com/multipath-tcp/mptcp_net-next/issues/182
Fixes: aa1fbd94e5
("mptcp: sockopt: add TCP_CONGESTION and TCP_INFO")
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bab09fe2f6
commit
20b5759f21
|
@ -2424,13 +2424,12 @@ static int __mptcp_init_sock(struct sock *sk)
|
||||||
timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
|
timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
|
||||||
timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
|
timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
|
||||||
|
|
||||||
tcp_assign_congestion_control(sk);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mptcp_init_sock(struct sock *sk)
|
static int mptcp_init_sock(struct sock *sk)
|
||||||
{
|
{
|
||||||
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
struct net *net = sock_net(sk);
|
struct net *net = sock_net(sk);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -2448,6 +2447,16 @@ static int mptcp_init_sock(struct sock *sk)
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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_sockets_allocated_inc(sk);
|
||||||
sk->sk_rcvbuf = sock_net(sk)->ipv4.sysctl_tcp_rmem[1];
|
sk->sk_rcvbuf = sock_net(sk)->ipv4.sysctl_tcp_rmem[1];
|
||||||
sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[1];
|
sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[1];
|
||||||
|
@ -2622,7 +2631,6 @@ static void __mptcp_destroy_sock(struct sock *sk)
|
||||||
sk_stream_kill_queues(sk);
|
sk_stream_kill_queues(sk);
|
||||||
xfrm_sk_free_policy(sk);
|
xfrm_sk_free_policy(sk);
|
||||||
|
|
||||||
tcp_cleanup_congestion_control(sk);
|
|
||||||
sk_refcnt_debug_release(sk);
|
sk_refcnt_debug_release(sk);
|
||||||
mptcp_dispose_initial_subflow(msk);
|
mptcp_dispose_initial_subflow(msk);
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
|
|
|
@ -258,6 +258,7 @@ struct mptcp_sock {
|
||||||
} rcvq_space;
|
} rcvq_space;
|
||||||
|
|
||||||
u32 setsockopt_seq;
|
u32 setsockopt_seq;
|
||||||
|
char ca_name[TCP_CA_NAME_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define mptcp_lock_sock(___sk, cb) do { \
|
#define mptcp_lock_sock(___sk, cb) do { \
|
||||||
|
|
|
@ -547,7 +547,7 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
tcp_set_congestion_control(sk, name, false, cap_net_admin);
|
strcpy(msk->ca_name, name);
|
||||||
|
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -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));
|
sock_valbool_flag(ssk, SOCK_DBG, sock_flag(sk, SOCK_DBG));
|
||||||
|
|
||||||
if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops)
|
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)
|
static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
|
||||||
|
|
Loading…
Reference in New Issue