Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jan 2012 19:20:33 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r230075 - in stable/8/sys: netinet netinet6
Message-ID:  <201201131920.q0DJKXCP076127@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Fri Jan 13 19:20:33 2012
New Revision: 230075
URL: http://svn.freebsd.org/changeset/base/230075

Log:
  MFC 229414,229476,229477:
  Various fixes to the SIOC[DG]LIFADDR ioctl handlers:
  - Grab a reference on any matching interface address (ifa) before dropping
    the IF_ADDR_LOCK() and release the reference after using it to prevent a
    potential use-after-free.
  - Fix the IPv4 ioctl handlers in in_lifaddr_ioctl() to work with IPv4
    interface addresses rather than IPv6.
  - Add missing interface address list locking in the IPv4 handlers.

Modified:
  stable/8/sys/netinet/in.c
  stable/8/sys/netinet6/in6.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/netinet/in.c
==============================================================================
--- stable/8/sys/netinet/in.c	Fri Jan 13 19:20:09 2012	(r230074)
+++ stable/8/sys/netinet/in.c	Fri Jan 13 19:20:33 2012	(r230075)
@@ -720,7 +720,7 @@ in_lifaddr_ioctl(struct socket *so, u_lo
 		if (iflr->flags & IFLR_PREFIX)
 			return (EINVAL);
 
-		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
+		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
 		bzero(&ifra, sizeof(ifra));
 		bcopy(iflr->iflr_name, ifra.ifra_name,
 			sizeof(ifra.ifra_name));
@@ -769,8 +769,9 @@ in_lifaddr_ioctl(struct socket *so, u_lo
 			}
 		}
 
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)	{
-			if (ifa->ifa_addr->sa_family != AF_INET6)
+			if (ifa->ifa_addr->sa_family != AF_INET)
 				continue;
 			if (match.s_addr == 0)
 				break;
@@ -779,6 +780,9 @@ in_lifaddr_ioctl(struct socket *so, u_lo
 			if (candidate.s_addr == match.s_addr)
 				break;
 		}
+		if (ifa != NULL)
+			ifa_ref(ifa);
+		IF_ADDR_UNLOCK(ifp);
 		if (ifa == NULL)
 			return (EADDRNOTAVAIL);
 		ia = (struct in_ifaddr *)ifa;
@@ -797,12 +801,13 @@ in_lifaddr_ioctl(struct socket *so, u_lo
 				in_mask2len(&ia->ia_sockmask.sin_addr);
 
 			iflr->flags = 0;	/*XXX*/
+			ifa_free(ifa);
 
 			return (0);
 		} else {
 			struct in_aliasreq ifra;
 
-			/* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
+			/* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
 			bzero(&ifra, sizeof(ifra));
 			bcopy(iflr->iflr_name, ifra.ifra_name,
 				sizeof(ifra.ifra_name));
@@ -815,6 +820,7 @@ in_lifaddr_ioctl(struct socket *so, u_lo
 			}
 			bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
 				ia->ia_sockmask.sin_len);
+			ifa_free(ifa);
 
 			return (in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
 			    ifp, td));

Modified: stable/8/sys/netinet6/in6.c
==============================================================================
--- stable/8/sys/netinet6/in6.c	Fri Jan 13 19:20:09 2012	(r230074)
+++ stable/8/sys/netinet6/in6.c	Fri Jan 13 19:20:33 2012	(r230075)
@@ -1655,6 +1655,8 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 			if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
 				break;
 		}
+		if (ifa != NULL)
+			ifa_ref(ifa);
 		IF_ADDR_UNLOCK(ifp);
 		if (!ifa)
 			return EADDRNOTAVAIL;
@@ -1667,16 +1669,20 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 			bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
 			error = sa6_recoverscope(
 			    (struct sockaddr_in6 *)&iflr->addr);
-			if (error != 0)
+			if (error != 0) {
+				ifa_free(ifa);
 				return (error);
+			}
 
 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
 				bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
 				    ia->ia_dstaddr.sin6_len);
 				error = sa6_recoverscope(
 				    (struct sockaddr_in6 *)&iflr->dstaddr);
-				if (error != 0)
+				if (error != 0) {
+					ifa_free(ifa);
 					return (error);
+				}
 			} else
 				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
 
@@ -1684,6 +1690,7 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 			    in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
 
 			iflr->flags = ia->ia6_flags;	/* XXX */
+			ifa_free(ifa);
 
 			return 0;
 		} else {
@@ -1707,6 +1714,7 @@ in6_lifaddr_ioctl(struct socket *so, u_l
 			    ia->ia_prefixmask.sin6_len);
 
 			ifra.ifra_flags = ia->ia6_flags;
+			ifa_free(ifa);
 			return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
 			    ifp, td);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201131920.q0DJKXCP076127>