summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-24 14:29:40 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-24 14:29:40 +0000
commitb1ee9361a4295c3daca88aba5ce6edf2f48e8456 (patch)
tree5685212063087b1b7ebe76d0436e7e0d689061af /sys/netinet/ip_input.c
parentcceae54c51a10e1742d7b182bb2136cb5c78cd38 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c15
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] = {
OpenPOWER on IntegriCloud