diff options
author | jhb <jhb@FreeBSD.org> | 2012-01-03 19:44:36 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-01-03 19:44:36 +0000 |
commit | badf97ee75299cfb893ff28bb70d0a5fc731398e (patch) | |
tree | 3e368202b18675d5456724b0a41c495cee3b4962 /sys/netinet6/in6.c | |
parent | 32180701de4dc720dfc0f25587a6c03c55c06cce (diff) | |
download | FreeBSD-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.c | 12 |
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); } |