Same as the support for tcpv4, we simply add the necessary checks so we
just look at our own sockets.

Signed-off-by: Hannes Frederic Sowa <han...@stressinduktion.org>
---
 net/ipv6/inet6_hashtables.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 8570e0e3016b65..05b71f0937e676 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -87,6 +87,7 @@ struct sock *__inet6_lookup_established(struct net *net,
                                           const u16 hnum,
                                           const int dif)
 {
+       struct afnetns *afnetns;
        struct sock *sk;
        const struct hlist_nulls_node *node;
        const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
@@ -97,11 +98,15 @@ struct sock *__inet6_lookup_established(struct net *net,
        unsigned int slot = hash & hashinfo->ehash_mask;
        struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
 
+       afnetns = ipv6_get_ifaddr_afnetns_rcu(net, daddr,
+                                             dev_get_by_index_rcu(net, dif));
 
 begin:
        sk_nulls_for_each_rcu(sk, node, &head->chain) {
                if (sk->sk_hash != hash)
                        continue;
+               if (sock_afnetns(sk) != afnetns)
+                       continue;
                if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif))
                        continue;
                if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
@@ -123,14 +128,15 @@ struct sock *__inet6_lookup_established(struct net *net,
 EXPORT_SYMBOL(__inet6_lookup_established);
 
 static inline int compute_score(struct sock *sk, struct net *net,
+                               struct afnetns *afnetns,
                                const unsigned short hnum,
                                const struct in6_addr *daddr,
                                const int dif, bool exact_dif)
 {
        int score = -1;
 
-       if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum &&
-           sk->sk_family == PF_INET6) {
+       if (net_eq(sock_net(sk), net) && sock_afnetns(sk) == afnetns &&
+           inet_sk(sk)->inet_num == hnum && sk->sk_family == PF_INET6) {
 
                score = 1;
                if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
@@ -162,10 +168,14 @@ struct sock *inet6_lookup_listener(struct net *net,
        int score, hiscore = 0, matches = 0, reuseport = 0;
        bool exact_dif = inet6_exact_dif_match(net, skb);
        struct sock *sk, *result = NULL;
+       struct afnetns *afnetns;
        u32 phash = 0;
 
+       afnetns = ipv6_get_ifaddr_afnetns_rcu(net, daddr, skb->dev);
+
        sk_for_each(sk, &ilb->head) {
-               score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
+               score = compute_score(sk, net, afnetns, hnum, daddr, dif,
+                                     exact_dif);
                if (score > hiscore) {
                        reuseport = sk->sk_reuseport;
                        if (reuseport) {
-- 
2.9.3

Reply via email to