]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: prefer socket bound to interface when not in VRF
authorMike Manning <mvrmanning@gmail.com>
Tue, 5 Oct 2021 13:03:42 +0000 (14:03 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Oct 2021 08:08:20 +0000 (10:08 +0200)
[ Upstream commit 8d6c414cd2fb74aa6812e9bfec6178f8246c4f3a ]

The commit 4810a2cd76ff ("net: ensure unbound datagram socket to be
chosen when not in a VRF") modified compute_score() so that a device
match is always made, not just in the case of an l3mdev skb, then
increments the score also for unbound sockets. This ensures that
sockets bound to an l3mdev are never selected when not in a VRF.
But as unbound and bound sockets are now scored equally, this results
in the last opened socket being selected if there are matches in the
default VRF for an unbound socket and a socket bound to a dev that is
not an l3mdev. However, handling prior to this commit was to always
select the bound socket in this case. Reinstate this handling by
incrementing the score only for bound sockets. The required isolation
due to choosing between an unbound socket and a socket bound to an
l3mdev remains in place due to the device match always being made.
The same approach is taken for compute_score() for stream sockets.

Fixes: 4810a2cd76ff ("net: ensure unbound datagram socket to be chosen when not in a VRF")
Fixes: 2a85acfe8989 ("net: ensure unbound stream socket to be chosen when not in a VRF")
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/cf0a8523-b362-1edf-ee78-eef63cbbb428@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/inet_hashtables.c
net/ipv4/udp.c
net/ipv6/inet6_hashtables.c
net/ipv6/udp.c

index 006a34b185378d6903020a4a054d552f5932fabc..72fdf1fcbcaa917c88945820f7f0a3be83a74994 100644 (file)
@@ -239,8 +239,10 @@ static inline int compute_score(struct sock *sk, struct net *net,
 
                if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
                        return -1;
+               score =  sk->sk_bound_dev_if ? 2 : 1;
 
-               score = sk->sk_family == PF_INET ? 2 : 1;
+               if (sk->sk_family == PF_INET)
+                       score++;
                if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
index de04d99418850f30a2239377a427ac10a466e59e..fdbd56ee1300cf975d1faea7ecd1cab35a355b6a 100644 (file)
@@ -386,7 +386,8 @@ static int compute_score(struct sock *sk, struct net *net,
                                        dif, sdif);
        if (!dev_match)
                return -1;
-       score += 4;
+       if (sk->sk_bound_dev_if)
+               score += 4;
 
        if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;
index fbe9d4295eac38d247aca362d6006cdec2d7f7da..ab12e00f6bfff2b647b970438aba60fcbf0e169b 100644 (file)
@@ -104,7 +104,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
                        return -1;
 
-               score = 1;
+               score =  sk->sk_bound_dev_if ? 2 : 1;
                if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
index 5b8266f3e47f030522cad050748d61991542f5f5..0f57c682afdd8559ff0651b60858bb0d803f8658 100644 (file)
@@ -133,7 +133,8 @@ static int compute_score(struct sock *sk, struct net *net,
        dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);
        if (!dev_match)
                return -1;
-       score++;
+       if (sk->sk_bound_dev_if)
+               score++;
 
        if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;