mptcp: explicitly specify sock family at subflow creation time
authorPaolo Abeni <pabeni@redhat.com>
Thu, 12 Jan 2023 17:42:51 +0000 (18:42 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 14 Jan 2023 05:55:45 +0000 (21:55 -0800)
Let the caller specify the to-be-created subflow family.

For a given MPTCP socket created with the AF_INET6 family, the current
userspace PM can already ask the kernel to create subflows in v4 and v6.
If "plain" IPv4 addresses are passed to the kernel, they are
automatically mapped in v6 addresses "by accident". This can be
problematic because the userspace will need to pass different addresses,
now the v4-mapped-v6 addresses to destroy this new subflow.

On the other hand, if the MPTCP socket has been created with the AF_INET
family, the command to create a subflow in v6 will be accepted but the
result will not be the one as expected as new subflow will be created in
IPv4 using part of the v6 addresses passed to the kernel: not creating
the expected subflow then.

No functional change intended for the in-kernel PM where an explicit
enforcement is currently in place. This arbitrary enforcement will be
leveraged by other patches in a future version.

Fixes: 702c2f646d42 ("mptcp: netlink: allow userspace-driven subflow establishment")
Cc: stable@vger.kernel.org
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c

index b7ad030dfe891c81a1f4ee0f3db18bf9058789ec..8cd6cc67c2c5cf9c94d9bb041b83058351c30cae 100644 (file)
@@ -98,7 +98,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        struct socket *ssock;
        int err;
 
-       err = mptcp_subflow_create_socket(sk, &ssock);
+       err = mptcp_subflow_create_socket(sk, sk->sk_family, &ssock);
        if (err)
                return err;
 
index a0d1658ce59eea250b03948665f52e86876c2490..a9e0355744b6a4ab1878858104bea054358d50d1 100644 (file)
@@ -641,7 +641,8 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
 /* called with sk socket lock held */
 int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
                            const struct mptcp_addr_info *remote);
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock);
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock);
 void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
                         struct sockaddr_storage *addr,
                         unsigned short family);
index bd387d4b5a38f4a20745c879fe83846a3396e6e6..ec54413fb31f7862ccf1602395235a7888e44dd4 100644 (file)
@@ -1547,7 +1547,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
        if (!mptcp_is_fully_established(sk))
                goto err_out;
 
-       err = mptcp_subflow_create_socket(sk, &sf);
+       err = mptcp_subflow_create_socket(sk, loc->family, &sf);
        if (err)
                goto err_out;
 
@@ -1660,7 +1660,9 @@ static void mptcp_subflow_ops_undo_override(struct sock *ssk)
 #endif
                ssk->sk_prot = &tcp_prot;
 }
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
+
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock)
 {
        struct mptcp_subflow_context *subflow;
        struct net *net = sock_net(sk);
@@ -1673,8 +1675,7 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
        if (unlikely(!sk->sk_socket))
                return -EINVAL;
 
-       err = sock_create_kern(net, sk->sk_family, SOCK_STREAM, IPPROTO_TCP,
-                              &sf);
+       err = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &sf);
        if (err)
                return err;