diff options
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
| -rw-r--r-- | net/ipv6/inet6_connection_sock.c | 19 | 
1 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 30647857a37..e4297a39367 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -32,6 +32,9 @@ int inet6_csk_bind_conflict(const struct sock *sk,  {  	const struct sock *sk2;  	const struct hlist_node *node; +	int reuse = sk->sk_reuse; +	int reuseport = sk->sk_reuseport; +	int uid = sock_i_uid((struct sock *)sk);  	/* We must walk the whole port owner list in this case. -DaveM */  	/* @@ -42,11 +45,17 @@ int inet6_csk_bind_conflict(const struct sock *sk,  		if (sk != sk2 &&  		    (!sk->sk_bound_dev_if ||  		     !sk2->sk_bound_dev_if || -		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && -		    (!sk->sk_reuse || !sk2->sk_reuse || -		     sk2->sk_state == TCP_LISTEN) && -		     ipv6_rcv_saddr_equal(sk, sk2)) -			break; +		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { +			if ((!reuse || !sk2->sk_reuse || +			     sk2->sk_state == TCP_LISTEN) && +			    (!reuseport || !sk2->sk_reuseport || +			     (sk2->sk_state != TCP_TIME_WAIT && +			      !uid_eq(uid, +				      sock_i_uid((struct sock *)sk2))))) { +				if (ipv6_rcv_saddr_equal(sk, sk2)) +					break; +			} +		}  	}  	return node != NULL;  |