Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Jan 2012 19:20:09 +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-9@freebsd.org
Subject:   svn commit: r230074 - in stable/9/sys: netinet netinet6
Message-ID:  <201201131920.q0DJK9iB076075@svn.freebsd.org>

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

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/9/sys/netinet/in.c
  stable/9/sys/netinet6/in6.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/amd64/include/xen/   (props changed)
  stable/9/sys/boot/   (props changed)
  stable/9/sys/boot/i386/efi/   (props changed)
  stable/9/sys/boot/ia64/efi/   (props changed)
  stable/9/sys/boot/ia64/ski/   (props changed)
  stable/9/sys/boot/powerpc/boot1.chrp/   (props changed)
  stable/9/sys/boot/powerpc/ofw/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)
  stable/9/sys/conf/   (props changed)
  stable/9/sys/contrib/dev/acpica/   (props changed)
  stable/9/sys/contrib/octeon-sdk/   (props changed)
  stable/9/sys/contrib/pf/   (props changed)
  stable/9/sys/contrib/x86emu/   (props changed)

Modified: stable/9/sys/netinet/in.c
==============================================================================
--- stable/9/sys/netinet/in.c	Fri Jan 13 19:13:43 2012	(r230073)
+++ stable/9/sys/netinet/in.c	Fri Jan 13 19:20:09 2012	(r230074)
@@ -704,7 +704,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));
@@ -753,8 +753,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;
@@ -763,6 +764,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;
@@ -781,12 +785,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));
@@ -799,6 +804,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/9/sys/netinet6/in6.c
==============================================================================
--- stable/9/sys/netinet6/in6.c	Fri Jan 13 19:13:43 2012	(r230073)
+++ stable/9/sys/netinet6/in6.c	Fri Jan 13 19:20:09 2012	(r230074)
@@ -1738,6 +1738,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;
@@ -1750,16 +1752,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));
 
@@ -1767,6 +1773,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 {
@@ -1790,6 +1797,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.q0DJK9iB076075>