summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-01-03 19:44:36 +0000
committerjhb <jhb@FreeBSD.org>2012-01-03 19:44:36 +0000
commitbadf97ee75299cfb893ff28bb70d0a5fc731398e (patch)
tree3e368202b18675d5456724b0a41c495cee3b4962 /sys/netinet6/in6.c
parent32180701de4dc720dfc0f25587a6c03c55c06cce (diff)
downloadFreeBSD-src-badf97ee75299cfb893ff28bb70d0a5fc731398e.zip
FreeBSD-src-badf97ee75299cfb893ff28bb70d0a5fc731398e.tar.gz
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
Diffstat (limited to 'sys/netinet6/in6.c')
-rw-r--r--sys/netinet6/in6.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 9ef25e7..b8e0504 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1767,6 +1767,8 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
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_long cmd, caddr_t data,
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_long cmd, caddr_t data,
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_long cmd, caddr_t data,
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);
}
OpenPOWER on IntegriCloud