Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jan 2012 19:44:36 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r229414 - head/sys/netinet6
Message-ID:  <201201031944.q03Jia46039559@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Tue Jan  3 19:44:36 2012
New Revision: 229414
URL: http://svn.freebsd.org/changeset/base/229414

Log:
  Grab a reference on the matching interface address (ifa) in the handling
  of the SIOC[DG]LIFADDR icotls before dropping the IF_ADDR_LOCK() and
  release the reference after using it.  This prevents the address from
  being potentially freed out from under the ioctl handler.
  
  Reviewed by:	bz
  MFC after:	1 week

Modified:
  head/sys/netinet6/in6.c

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c	Tue Jan  3 19:41:36 2012	(r229413)
+++ head/sys/netinet6/in6.c	Tue Jan  3 19:44:36 2012	(r229414)
@@ -1767,6 +1767,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;
@@ -1779,16 +1781,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));
 
@@ -1796,6 +1802,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 {
@@ -1819,6 +1826,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?201201031944.q03Jia46039559>