svn commit: r194835 - head/sys/netinet

Robert Watson rwatson at FreeBSD.org
Wed Jun 24 14:29:40 UTC 2009


Author: rwatson
Date: Wed Jun 24 14:29:40 2009
New Revision: 194835
URL: http://svn.freebsd.org/changeset/base/194835

Log:
  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

Modified:
  head/sys/netinet/ip_input.c

Modified: head/sys/netinet/ip_input.c
==============================================================================
--- head/sys/netinet/ip_input.c	Wed Jun 24 13:38:08 2009	(r194834)
+++ head/sys/netinet/ip_input.c	Wed Jun 24 14:29:40 2009	(r194835)
@@ -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 fibn
 {
 	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 fibn
 	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] = {


More information about the svn-src-head mailing list