diff options
author | csjp <csjp@FreeBSD.org> | 2005-09-10 15:12:24 +0000 |
---|---|---|
committer | csjp <csjp@FreeBSD.org> | 2005-09-10 15:12:24 +0000 |
commit | 7bdd5fbb1cb592f83faf06d49d6403302c17f0dc (patch) | |
tree | f5c252eab1f591e17ce8431aebeb7b4cc8e06268 /sys/net/rtsock.c | |
parent | 35fe4fa9a94c4dcf6a227617bc88deb17847265b (diff) | |
download | FreeBSD-src-7bdd5fbb1cb592f83faf06d49d6403302c17f0dc.zip FreeBSD-src-7bdd5fbb1cb592f83faf06d49d6403302c17f0dc.tar.gz |
Protect interface and address lists using the appropriate mutex. These
locks were not aquired because the user buffers were not wired, thus it was
possible that that SYSCTL_OUT could sleep, causing a number of different
problems such as lock ordering issues and dead locks.
-Wire user supplied buffer to ensure SYSCTL_OUT will not sleep.
-Pickup ifnet locks to protect the list.
-Where applicable pickup address locks.
-Pickup radix node head locks.
-Remove splnet stubs
-Remove various comments about locking here, because they are no
longer needed.
It is the hope that these changes will make sysctl_rtsock MP safe.
MFC after: 3 weeks
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r-- | sys/net/rtsock.c | 32 |
1 files changed, 16 insertions, 16 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index cf34315..cceeb19 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1089,7 +1089,7 @@ sysctl_iflist(int af, struct walkarg *w) int len, error = 0; bzero((caddr_t)&info, sizeof(info)); - /* IFNET_RLOCK(); */ /* could sleep XXX */ + IFNET_RLOCK(); TAILQ_FOREACH(ifp, &ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; @@ -1136,7 +1136,7 @@ sysctl_iflist(int af, struct walkarg *w) info.rti_info[RTAX_BRD] = NULL; } done: - /* IFNET_RUNLOCK(); */ /* XXX */ + IFNET_RUNLOCK(); return (error); } @@ -1150,17 +1150,13 @@ sysctl_ifmalist(int af, struct walkarg *w) struct ifaddr *ifa; bzero((caddr_t)&info, sizeof(info)); - /* IFNET_RLOCK(); */ /* could sleep XXX */ + IFNET_RLOCK(); TAILQ_FOREACH(ifp, &ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; ifa = ifaddr_byindex(ifp->if_index); info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL; - - /* - * XXXRW: Can't acquire IF_ADDR_LOCK() due to call - * to SYSCTL_OUT(). - */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (af && af != ifma->ifma_addr->sa_family) continue; @@ -1180,13 +1176,16 @@ sysctl_ifmalist(int af, struct walkarg *w) ifmam->ifmam_flags = 0; ifmam->ifmam_addrs = info.rti_addrs; error = SYSCTL_OUT(w->w_req, w->w_tmem, len); - if (error) + if (error) { + IF_ADDR_UNLOCK(ifp); goto done; + } } } + IF_ADDR_UNLOCK(ifp); } done: - /* IFNET_RUNLOCK(); */ /* XXX */ + IFNET_RUNLOCK(); return (error); } @@ -1196,7 +1195,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) int *name = (int *)arg1; u_int namelen = arg2; struct radix_node_head *rnh; - int i, lim, s, error = EINVAL; + int i, lim, error = EINVAL; u_char af; struct walkarg w; @@ -1214,7 +1213,9 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) w.w_arg = name[2]; w.w_req = req; - s = splnet(); + error = sysctl_wire_old_buffer(req, 0); + if (error) + return (error); switch (w.w_op) { case NET_RT_DUMP: @@ -1226,10 +1227,10 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) i = lim = af; for (error = 0; error == 0 && i <= lim; i++) if ((rnh = rt_tables[i]) != NULL) { - /* RADIX_NODE_HEAD_LOCK(rnh); */ + RADIX_NODE_HEAD_LOCK(rnh); error = rnh->rnh_walktree(rnh, - sysctl_dumpentry, &w);/* could sleep XXX */ - /* RADIX_NODE_HEAD_UNLOCK(rnh); */ + sysctl_dumpentry, &w); + RADIX_NODE_HEAD_UNLOCK(rnh); } else if (af != 0) error = EAFNOSUPPORT; break; @@ -1242,7 +1243,6 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) error = sysctl_ifmalist(af, &w); break; } - splx(s); if (w.w_tmem) free(w.w_tmem, M_RTABLE); return (error); |