Commit 2efc5e41 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller

[UDPv6] fix udp_v6_get_port introduced by the sock splitup

It is the same bug fixed some months ago in tcp_v6_get_port,
i.e. we can't touch ipv6 private areas without checking if
the socket is AF_INET6.
parent bd2c9a34
...@@ -50,6 +50,18 @@ ...@@ -50,6 +50,18 @@
struct udp_mib udp_stats_in6[NR_CPUS*2]; struct udp_mib udp_stats_in6[NR_CPUS*2];
static __inline__ int udv6_rcv_saddr_equal(struct sock *sk, struct sock *sk2)
{
struct ipv6_pinfo *np = inet6_sk(sk);
int addr_type = ipv6_addr_type(&np->rcv_saddr);
return !inet_sk(sk2)->rcv_saddr || addr_type == IPV6_ADDR_ANY ||
(sk2->family == AF_INET6 &&
!ipv6_addr_cmp(&np->rcv_saddr, &inet6_sk(sk2)->rcv_saddr)) ||
(addr_type == IPV6_ADDR_MAPPED && sk2->family == AF_INET &&
inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr);
}
/* Grrr, addr_type already calculated by caller, but I don't want /* Grrr, addr_type already calculated by caller, but I don't want
* to add some silly "cookie" argument to this method just for that. * to add some silly "cookie" argument to this method just for that.
*/ */
...@@ -98,25 +110,15 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -98,25 +110,15 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum)
udp_port_rover = snum = result; udp_port_rover = snum = result;
} else { } else {
struct sock *sk2; struct sock *sk2;
struct ipv6_pinfo *np = inet6_sk(sk);
int addr_type = ipv6_addr_type(&np->rcv_saddr);
for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
sk2 != NULL; sk2 != NULL;
sk2 = sk2->next) { sk2 = sk2->next) {
struct inet_opt *inet2 = inet_sk(sk2); if (inet_sk(sk2)->num == snum &&
struct ipv6_pinfo *np2 = inet6_sk(sk2);
if (inet2->num == snum &&
sk2 != sk && sk2 != sk &&
sk2->bound_dev_if == sk->bound_dev_if && sk2->bound_dev_if == sk->bound_dev_if &&
(!inet2->rcv_saddr || (!sk2->reuse || !sk->reuse) &&
addr_type == IPV6_ADDR_ANY || udv6_rcv_saddr_equal(sk, sk2))
!ipv6_addr_cmp(&np->rcv_saddr, &np2->rcv_saddr) ||
(addr_type == IPV6_ADDR_MAPPED &&
sk2->family == AF_INET &&
inet_sk(sk)->rcv_saddr == inet2->rcv_saddr)) &&
(!sk2->reuse || !sk->reuse))
goto fail; goto fail;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment