]> Pileus Git - ~andy/linux/blobdiff - net/ipv6/inet6_connection_sock.c
tcp: ipv6: bind() use stronger condition for bind_conflict
[~andy/linux] / net / ipv6 / inet6_connection_sock.c
index b386a2ce4c6fdd4b01afe3903e6988fbdeaa2043..5f25510f584ef8ce6462e3b2fd667dc2dc553471 100644 (file)
@@ -31,7 +31,6 @@ int inet6_csk_bind_conflict(const struct sock *sk,
                            const struct inet_bind_bucket *tb, bool relax)
 {
        const struct sock *sk2;
-       const struct hlist_node *node;
        int reuse = sk->sk_reuse;
        int reuseport = sk->sk_reuseport;
        kuid_t uid = sock_i_uid((struct sock *)sk);
@@ -41,7 +40,7 @@ int inet6_csk_bind_conflict(const struct sock *sk,
         * See comment in inet_csk_bind_conflict about sock lookup
         * vs net namespaces issues.
         */
-       sk_for_each_bound(sk2, node, &tb->owners) {
+       sk_for_each_bound(sk2, &tb->owners) {
                if (sk != sk2 &&
                    (!sk->sk_bound_dev_if ||
                     !sk2->sk_bound_dev_if ||
@@ -55,10 +54,14 @@ int inet6_csk_bind_conflict(const struct sock *sk,
                                if (ipv6_rcv_saddr_equal(sk, sk2))
                                        break;
                        }
+                       if (!relax && reuse && sk2->sk_reuse &&
+                           sk2->sk_state != TCP_LISTEN &&
+                           ipv6_rcv_saddr_equal(sk, sk2))
+                               break;
                }
        }
 
-       return node != NULL;
+       return sk2 != NULL;
 }
 
 EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);