diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-12-20 18:33:44 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2016-12-20 18:33:44 +0000 |
commit | 224769b48e66fb93384e8bf2e225552d3706a2c7 (patch) | |
tree | ce9b82c59578aba2b6b21289f3dcba94d2515ee1 /sys | |
parent | e5175244e0715bec617be80d08e27d4d5daa2978 (diff) |
A NET_LOCK() was is missing in tcp_sysctl() which shows up as spl
softnet assert failures. It is better to place the lock into
net_sysctl() where all the protocol sysctls are called via pr_sysctl.
As calling sysctl(2) is in the slow path, doing fine grained locking
has no benefit. Many sysctl cases copy out a struct. Having a
lock around that keeps the struct consistent. Put assertions in
the protocol sysctls that need it.
OK mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_domain.c | 24 | ||||
-rw-r--r-- | sys/net/rtsock.c | 14 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 8 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 13 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 4 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 11 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 16 |
7 files changed, 43 insertions, 47 deletions
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index fb0cf9f46dc..34c7aa66e7f 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_domain.c,v 1.46 2016/11/22 10:32:31 mpi Exp $ */ +/* $OpenBSD: uipc_domain.c,v 1.47 2016/12/20 18:33:43 bluhm Exp $ */ /* $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $ */ /* @@ -165,7 +165,7 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, { struct domain *dp; struct protosw *pr; - int family, protocol; + int s, error, family, protocol; /* * All sysctl names at this level are nonterminal. @@ -199,18 +199,26 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, #ifdef MPLS /* XXX WARNING: big fat ugly hack */ /* stupid net.mpls is special as it does not have a protocol */ - if (family == PF_MPLS) - return (dp->dom_protosw[0].pr_sysctl(name + 1, namelen - 1, - oldp, oldlenp, newp, newlen)); + if (family == PF_MPLS) { + NET_LOCK(s); + error = (dp->dom_protosw[0].pr_sysctl)(name + 1, namelen - 1, + oldp, oldlenp, newp, newlen); + NET_UNLOCK(s); + return (error); + } #endif if (namelen < 3) return (EISDIR); /* overloaded */ protocol = name[1]; for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) - if (pr->pr_protocol == protocol && pr->pr_sysctl) - return ((*pr->pr_sysctl)(name + 2, namelen - 2, - oldp, oldlenp, newp, newlen)); + if (pr->pr_protocol == protocol && pr->pr_sysctl) { + NET_LOCK(s); + error = (*pr->pr_sysctl)(name + 2, namelen - 2, + oldp, oldlenp, newp, newlen); + NET_UNLOCK(s); + return (error); + } return (ENOPROTOOPT); } diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 92504f51f3d..d56a8f5cbea 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.211 2016/12/19 08:36:49 mpi Exp $ */ +/* $OpenBSD: rtsock.c,v 1.212 2016/12/20 18:33:43 bluhm Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -1563,12 +1563,14 @@ int sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, size_t newlen) { - int i, s, error = EINVAL; + int i, error = EINVAL; u_char af; struct walkarg w; struct rt_tableinfo tableinfo; u_int tableid = 0; + NET_ASSERT_LOCKED(); + if (new) return (EPERM); if (namelen < 3 || namelen > 4) @@ -1588,7 +1590,6 @@ sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, } else tableid = curproc->p_p->ps_rtableid; - s = splsoftnet(); switch (w.w_op) { case NET_RT_DUMP: case NET_RT_FLAGS: @@ -1611,25 +1612,20 @@ sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new, case NET_RT_STATS: error = sysctl_rdstruct(where, given, new, &rtstat, sizeof(rtstat)); - splx(s); return (error); case NET_RT_TABLE: tableid = w.w_arg; - if (!rtable_exists(tableid)) { - splx(s); + if (!rtable_exists(tableid)) return (ENOENT); - } tableinfo.rti_tableid = tableid; tableinfo.rti_domainid = rtable_l2(tableid); error = sysctl_rdstruct(where, given, new, &tableinfo, sizeof(tableinfo)); - splx(s); return (error); case NET_RT_IFNAMES: error = sysctl_ifnames(&w); break; } - splx(s); free(w.w_tmem, M_RTABLE, 0); w.w_needed += w.w_given; if (where) { diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 56df4adc6d0..35db6be43ea 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_icmp.c,v 1.158 2016/12/19 08:36:49 mpi Exp $ */ +/* $OpenBSD: ip_icmp.c,v 1.159 2016/12/20 18:33:43 bluhm Exp $ */ /* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ /* @@ -878,13 +878,14 @@ int icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - int s, error; + int error; + + NET_ASSERT_LOCKED(); /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); - NET_LOCK(s); switch (name[0]) { case ICMPCTL_REDIRTIMEOUT: @@ -921,7 +922,6 @@ icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, error = ENOPROTOOPT; break; } - NET_UNLOCK(s); return (error); } diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index c03b2ae39ac..5243e38b6b3 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.290 2016/12/19 09:22:24 rzalamena Exp $ */ +/* $OpenBSD: ip_input.c,v 1.291 2016/12/20 18:33:43 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -1557,12 +1557,14 @@ int ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { - int s, error; + int error; #ifdef MROUTING extern int ip_mrtproto; extern struct mrtstat mrtstat; #endif + NET_ASSERT_LOCKED(); + /* Almost all sysctl names at this level are terminal. */ if (namelen != 1 && name[0] != IPCTL_IFQUEUE) return (ENOTDIR); @@ -1587,21 +1589,16 @@ ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) { - NET_LOCK(s); rt_timer_queue_destroy(ip_mtudisc_timeout_q); ip_mtudisc_timeout_q = NULL; - NET_UNLOCK(s); } return error; case IPCTL_MTUDISCTIMEOUT: error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc_timeout); - if (ip_mtudisc_timeout_q != NULL) { - NET_LOCK(s); + if (ip_mtudisc_timeout_q != NULL) rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); - NET_UNLOCK(s); - } return (error); case IPCTL_IPSEC_ENC_ALGORITHM: return (sysctl_tstring(oldp, oldlenp, newp, newlen, diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index ed781bafdd7..5cd71d38c04 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.138 2016/12/20 14:10:00 mpi Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.139 2016/12/20 18:33:43 bluhm Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -846,6 +846,8 @@ tcp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, { int error, nval; + NET_ASSERT_LOCKED(); + /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 3643cedd8ea..ee25a811a43 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_input.c,v 1.171 2016/12/19 08:36:50 mpi Exp $ */ +/* $OpenBSD: ip6_input.c,v 1.172 2016/12/20 18:33:43 bluhm Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -1369,7 +1369,9 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, extern int ip6_mrtproto; extern struct mrt6stat mrt6stat; #endif - int error, s; + int error; + + NET_ASSERT_LOCKED(); /* Almost all sysctl names at this level are terminal. */ if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE) @@ -1409,12 +1411,9 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, case IPV6CTL_MTUDISCTIMEOUT: error = sysctl_int(oldp, oldlenp, newp, newlen, &ip6_mtudisc_timeout); - if (icmp6_mtudisc_timeout_q != NULL) { - s = splsoftnet(); + if (icmp6_mtudisc_timeout_q != NULL) rt_timer_queue_change(icmp6_mtudisc_timeout_q, ip6_mtudisc_timeout); - splx(s); - } return (error); case IPV6CTL_IFQUEUE: return (sysctl_niq(name + 1, namelen - 1, diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 0f0c83b2400..cf59c02f31e 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.198 2016/12/19 08:36:50 mpi Exp $ */ +/* $OpenBSD: nd6.c,v 1.199 2016/12/20 18:33:43 bluhm Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -1639,6 +1639,8 @@ nd6_sysctl(int name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) size_t ol; int error; + NET_ASSERT_LOCKED(); + error = 0; if (newp) @@ -1678,14 +1680,12 @@ nd6_sysctl(int name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) int fill_drlist(void *oldp, size_t *oldlenp, size_t ol) { - int error = 0, s; + int error = 0; struct in6_defrouter *d = NULL, *de = NULL; struct nd_defrouter *dr; time_t expire; size_t l; - s = splsoftnet(); - if (oldp) { d = (struct in6_defrouter *)oldp; de = (struct in6_defrouter *)((caddr_t)oldp + *oldlenp); @@ -1721,22 +1721,18 @@ fill_drlist(void *oldp, size_t *oldlenp, size_t ol) } else *oldlenp = l; - splx(s); - return (error); } int fill_prlist(void *oldp, size_t *oldlenp, size_t ol) { - int error = 0, s; + int error = 0; struct nd_prefix *pr; char *p = NULL, *ps = NULL; char *pe = NULL; size_t l; - s = splsoftnet(); - if (oldp) { ps = p = (char *)oldp; pe = (char *)oldp + *oldlenp; @@ -1817,7 +1813,5 @@ fill_prlist(void *oldp, size_t *oldlenp, size_t ol) } else *oldlenp = l; - splx(s); - return (error); } |