[UDP]: Do not allow specific bind when wildcard bind exists.
When allocating local ports, do not allow a bind to a port with a specific local address when a bind to that port with a wildcard local address already exists. Noticed by Linus. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b7b5f487ab
commit
de34ed91c4
1 changed files with 33 additions and 8 deletions
|
@ -203,6 +203,13 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
|
||||||
result = sysctl_local_port_range[0]
|
result = sysctl_local_port_range[0]
|
||||||
+ ((result - sysctl_local_port_range[0]) &
|
+ ((result - sysctl_local_port_range[0]) &
|
||||||
(UDP_HTABLE_SIZE - 1));
|
(UDP_HTABLE_SIZE - 1));
|
||||||
|
hash = hash_port_and_addr(result, 0);
|
||||||
|
if (__udp_lib_port_inuse(hash, result,
|
||||||
|
0, udptable))
|
||||||
|
continue;
|
||||||
|
if (!inet_sk(sk)->rcv_saddr)
|
||||||
|
break;
|
||||||
|
|
||||||
hash = hash_port_and_addr(result,
|
hash = hash_port_and_addr(result,
|
||||||
inet_sk(sk)->rcv_saddr);
|
inet_sk(sk)->rcv_saddr);
|
||||||
if (! __udp_lib_port_inuse(hash, result,
|
if (! __udp_lib_port_inuse(hash, result,
|
||||||
|
@ -214,18 +221,36 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
|
||||||
gotit:
|
gotit:
|
||||||
*port_rover = snum = result;
|
*port_rover = snum = result;
|
||||||
} else {
|
} else {
|
||||||
hash = hash_port_and_addr(snum, inet_sk(sk)->rcv_saddr);
|
hash = hash_port_and_addr(snum, 0);
|
||||||
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
|
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
|
||||||
|
|
||||||
sk_for_each(sk2, node, head)
|
sk_for_each(sk2, node, head)
|
||||||
if (sk2->sk_hash == hash &&
|
if (sk2->sk_hash == hash &&
|
||||||
sk2 != sk &&
|
sk2 != sk &&
|
||||||
inet_sk(sk2)->num == snum &&
|
inet_sk(sk2)->num == snum &&
|
||||||
(!sk2->sk_reuse || !sk->sk_reuse) &&
|
(!sk2->sk_reuse || !sk->sk_reuse) &&
|
||||||
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
|
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
|
||||||
|| sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
|
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
|
||||||
(*saddr_comp)(sk, sk2) )
|
(*saddr_comp)(sk, sk2))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (inet_sk(sk)->rcv_saddr) {
|
||||||
|
hash = hash_port_and_addr(snum,
|
||||||
|
inet_sk(sk)->rcv_saddr);
|
||||||
|
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
|
||||||
|
|
||||||
|
sk_for_each(sk2, node, head)
|
||||||
|
if (sk2->sk_hash == hash &&
|
||||||
|
sk2 != sk &&
|
||||||
|
inet_sk(sk2)->num == snum &&
|
||||||
|
(!sk2->sk_reuse || !sk->sk_reuse) &&
|
||||||
|
(!sk2->sk_bound_dev_if ||
|
||||||
|
!sk->sk_bound_dev_if ||
|
||||||
|
sk2->sk_bound_dev_if ==
|
||||||
|
sk->sk_bound_dev_if) &&
|
||||||
|
(*saddr_comp)(sk, sk2))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inet_sk(sk)->num = snum;
|
inet_sk(sk)->num = snum;
|
||||||
sk->sk_hash = hash;
|
sk->sk_hash = hash;
|
||||||
|
|
Loading…
Reference in a new issue