summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-04-19 22:16:19 +0000
committerrwatson <rwatson@FreeBSD.org>2009-04-19 22:16:19 +0000
commit38c104950f32d836c5f70ed62933baf00b7cfeaf (patch)
tree5e9c214883179a99f30b2df323de46dcdbaef62f
parent80e4437a3b63e37efc7987db0e7f044546e89418 (diff)
downloadFreeBSD-src-38c104950f32d836c5f70ed62933baf00b7cfeaf.zip
FreeBSD-src-38c104950f32d836c5f70ed62933baf00b7cfeaf.tar.gz
Protect against some writer-writer races in in_control() by acquiring
the interface address list lock around interface address list modifications. More to do here. MFC after: 2 weeks
-rw-r--r--sys/netinet/in.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 1423e81..bb3973c 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -330,14 +330,12 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* Protect from ipintr() traversing address list
* while we're modifying it.
*/
- s = splnet();
ifa = &ia->ia_ifa;
IFA_LOCK_INIT(ifa);
ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
ifa->ifa_refcnt = 1;
- TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
ia->ia_sockmask.sin_len = 8;
ia->ia_sockmask.sin_family = AF_INET;
@@ -347,6 +345,10 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
}
ia->ia_ifp = ifp;
+ IF_ADDR_LOCK(ifp);
+ TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
+ IF_ADDR_UNLOCK(ifp);
+ s = splnet();
TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
splx(s);
iaIsNew = 1;
@@ -512,8 +514,10 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* Protect from ipintr() traversing address list while we're modifying
* it.
*/
- s = splnet();
+ IF_ADDR_LOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+ IF_ADDR_UNLOCK(ifp);
+ s = splnet();
TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
if (ia->ia_addr.sin_family == AF_INET) {
LIST_REMOVE(ia, ia_hash);
OpenPOWER on IntegriCloud