diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-06-24 14:29:40 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-06-24 14:29:40 +0000 |
commit | b1ee9361a4295c3daca88aba5ce6edf2f48e8456 (patch) | |
tree | 5685212063087b1b7ebe76d0436e7e0d689061af | |
parent | cceae54c51a10e1742d7b182bb2136cb5c78cd38 (diff) | |
download | FreeBSD-src-b1ee9361a4295c3daca88aba5ce6edf2f48e8456.zip FreeBSD-src-b1ee9361a4295c3daca88aba5ce6edf2f48e8456.tar.gz |
Clear 'ia' after iterating if_addrhead for unicast address matching: since
'ifa' was used as the TAILQ_FOREACH() iterator argument, and 'ia' was just
derived form it, it could be left non-NULL which confused later
conditional freeing code. This could cause kernel panics if multicast IP
packets were received. [1]
Call 'struct in_ifaddr *' in ip_rtaddr() 'ia', not 'ifa' in keeping with
normal conventions.
When 'ipstealth' is enabled returns from ip_input early, properly release
the 'ia' reference.
Reported by: lstewart, sam [1]
MFC after: 6 weeks
-rw-r--r-- | sys/netinet/ip_input.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index be4b084..81b8f8f3 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -661,6 +661,7 @@ passin: #endif } IF_ADDR_UNLOCK(ifp); + ia = NULL; } /* RFC 3927 2.7: Do not forward datagrams for 169.254.0.0/16. */ if (IN_LINKLOCAL(ntohl(ip->ip_dst.s_addr))) { @@ -738,9 +739,11 @@ ours: * IPSTEALTH: Process non-routing options only * if the packet is destined for us. */ - if (V_ipstealth && hlen > sizeof (struct ip) && - ip_dooptions(m, 1)) + if (V_ipstealth && hlen > sizeof (struct ip) && ip_dooptions(m, 1)) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); return; + } #endif /* IPSTEALTH */ /* Count the packet in the ip address stats */ @@ -1349,7 +1352,7 @@ ip_rtaddr(struct in_addr dst, u_int fibnum) { struct route sro; struct sockaddr_in *sin; - struct in_ifaddr *ifa; + struct in_ifaddr *ia; bzero(&sro, sizeof(sro)); sin = (struct sockaddr_in *)&sro.ro_dst; @@ -1361,10 +1364,10 @@ ip_rtaddr(struct in_addr dst, u_int fibnum) if (sro.ro_rt == NULL) return (NULL); - ifa = ifatoia(sro.ro_rt->rt_ifa); - ifa_ref(&ifa->ia_ifa); + ia = ifatoia(sro.ro_rt->rt_ifa); + ifa_ref(&ia->ia_ifa); RTFREE(sro.ro_rt); - return (ifa); + return (ia); } u_char inetctlerrmap[PRC_NCMDS] = { |