Commit b6e4a1ae authored by Mat Martineau's avatar Mat Martineau Committed by David S. Miller

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: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6f08e98d
...@@ -755,60 +755,50 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname, ...@@ -755,60 +755,50 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen) char __user *optval, unsigned int optlen)
{ {
struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_sock *msk = mptcp_sk(sk);
int ret = -EOPNOTSUPP;
struct socket *ssock; struct socket *ssock;
struct sock *ssk;
pr_debug("msk=%p", msk); pr_debug("msk=%p", msk);
/* @@ the meaning of setsockopt() when the socket is connected and /* @@ 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); lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE); ssock = __mptcp_tcp_fallback(msk);
if (IS_ERR(ssock)) { if (ssock)
release_sock(sk); return tcp_setsockopt(ssock->sk, level, optname, optval,
return ret; optlen);
}
ssk = ssock->sk;
sock_hold(ssk);
release_sock(sk); release_sock(sk);
ret = tcp_setsockopt(ssk, level, optname, optval, optlen); return -EOPNOTSUPP;
sock_put(ssk);
return ret;
} }
static int mptcp_getsockopt(struct sock *sk, int level, int optname, static int mptcp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *option) char __user *optval, int __user *option)
{ {
struct mptcp_sock *msk = mptcp_sk(sk); struct mptcp_sock *msk = mptcp_sk(sk);
int ret = -EOPNOTSUPP;
struct socket *ssock; struct socket *ssock;
struct sock *ssk;
pr_debug("msk=%p", msk); pr_debug("msk=%p", msk);
/* @@ the meaning of getsockopt() when the socket is connected and /* @@ 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 socket options are passed through
* to the one remaining subflow.
*/ */
lock_sock(sk); lock_sock(sk);
ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE); ssock = __mptcp_tcp_fallback(msk);
if (IS_ERR(ssock)) { if (ssock)
release_sock(sk); return tcp_getsockopt(ssock->sk, level, optname, optval,
return ret; option);
}
ssk = ssock->sk;
sock_hold(ssk);
release_sock(sk); release_sock(sk);
ret = tcp_getsockopt(ssk, level, optname, optval, option); return -EOPNOTSUPP;
sock_put(ssk);
return ret;
} }
static int mptcp_get_port(struct sock *sk, unsigned short snum) static int mptcp_get_port(struct sock *sk, unsigned short snum)
......
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