mptcp: Protect subflow socket options before connection completes

Userspace should not be able to directly manipulate subflow socket
options before a connection is established since it is not yet known if
it will be an MPTCP subflow or a TCP fallback subflow. TCP fallback
subflows can be more directly controlled by userspace because they are
regular TCP connections, while MPTCP subflow sockets need to be
configured for the specific needs of MPTCP. Use the same logic as
sendmsg/recvmsg to ensure that socket option calls are only passed
through to known TCP fallback subflows.

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:
Mat Martineau 2020-02-14 14:14:29 -08:00 committed by David S. Miller
parent 6f08e98d62
commit b6e4a1aeeb

View File

@ -755,60 +755,50 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen)
{
struct mptcp_sock *msk = mptcp_sk(sk);
int ret = -EOPNOTSUPP;
struct socket *ssock;
struct sock *ssk;
pr_debug("msk=%p", msk);
/* @@ the meaning of setsockopt() when the socket is connected and
* there are multiple subflows is not defined.
* there are multiple subflows is not yet defined. It is up to the
* MPTCP-level socket to configure the subflows until the subflow
* is in TCP fallback, when TCP socket options are passed through
* to the one remaining subflow.
*/
lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
if (IS_ERR(ssock)) {
release_sock(sk);
return ret;
}
ssock = __mptcp_tcp_fallback(msk);
if (ssock)
return tcp_setsockopt(ssock->sk, level, optname, optval,
optlen);
ssk = ssock->sk;
sock_hold(ssk);
release_sock(sk);
ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
sock_put(ssk);
return ret;
return -EOPNOTSUPP;
}
static int mptcp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *option)
{
struct mptcp_sock *msk = mptcp_sk(sk);
int ret = -EOPNOTSUPP;
struct socket *ssock;
struct sock *ssk;
pr_debug("msk=%p", msk);
/* @@ the meaning of getsockopt() when the socket is connected and
* there are multiple subflows is not defined.
/* @@ the meaning of setsockopt() when the socket is connected and
* there are multiple subflows is not yet defined. It is up to the
* MPTCP-level socket to configure the subflows until the subflow
* is in TCP fallback, when socket options are passed through
* to the one remaining subflow.
*/
lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
if (IS_ERR(ssock)) {
release_sock(sk);
return ret;
}
ssock = __mptcp_tcp_fallback(msk);
if (ssock)
return tcp_getsockopt(ssock->sk, level, optname, optval,
option);
ssk = ssock->sk;
sock_hold(ssk);
release_sock(sk);
ret = tcp_getsockopt(ssk, level, optname, optval, option);
sock_put(ssk);
return ret;
return -EOPNOTSUPP;
}
static int mptcp_get_port(struct sock *sk, unsigned short snum)