[PATCH mptcp-next v4 01/10] mptcp: preserve msk's sk_bound_dev_if on PM-default subflows

Geliang Tang <[email protected]> Thu, 30 Jul 2026 10:53:54 +0800
Newsgroups dev.linux.lists.mptcp
Message-ID <fc150fbcf8384d9ef0b3c650de3759399773a144.1785378180.git.tanggeliang@kylinos.cn>
From: Geliang Tang <[email protected]>

When the path manager creates a new subflow via __mptcp_subflow_connect(),
it currently writes local->ifindex to ssk->sk_bound_dev_if unconditionally.
The value was previously synced from the msk by mptcp_sockopt_sync_locked()
-> sync_socket_options(), so the unconditional write in the connect path
overwrites that inheritance.

When the path manager leaves local->ifindex at 0 (no interface pinned
for this subflow), the write wipes the synced value and clears any
SO_BINDTODEVICE / SO_BINDTOIFINDEX binding the user set on the msk. The
subflow then becomes free to route over any interface, bypassing VRF and
per-interface binding restrictions the user explicitly requested on the
master socket.

Only override sk_bound_dev_if when the path manager actually picked an
interface for this subflow; otherwise keep the value inherited from the
msk.

Signed-off-by: Geliang Tang <[email protected]>
---
 net/mptcp/subflow.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 8e386899ceb9..c39243c85f50 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1667,7 +1667,15 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,
 	if (addr.ss_family == AF_INET6)
 		addrlen = sizeof(struct sockaddr_in6);
 #endif
-	ssk->sk_bound_dev_if = local->ifindex;
+	/* Only override the bound device if the path manager picked one.
+	 * When local->ifindex == 0 the subflow must inherit sk_bound_dev_if
+	 * synced from the msk via mptcp_sockopt_sync_locked() - otherwise
+	 * SO_BINDTODEVICE / SO_BINDTOIFINDEX set on the master socket would
+	 * be silently cleared, letting traffic route over unintended
+	 * interfaces (bypassing VRF / interface-binding restrictions).
+	 */
+	if (local->ifindex)
+		ssk->sk_bound_dev_if = local->ifindex;
 	err = kernel_bind(sf, (struct sockaddr_unsized *)&addr, addrlen);
 	if (err) {
 		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNTXBINDERR);
-- 
2.53.0