summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2016-12-20 18:33:44 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2016-12-20 18:33:44 +0000
commit224769b48e66fb93384e8bf2e225552d3706a2c7 (patch)
treece9b82c59578aba2b6b21289f3dcba94d2515ee1 /sys
parente5175244e0715bec617be80d08e27d4d5daa2978 (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.c24
-rw-r--r--sys/net/rtsock.c14
-rw-r--r--sys/netinet/ip_icmp.c8
-rw-r--r--sys/netinet/ip_input.c13
-rw-r--r--sys/netinet/tcp_usrreq.c4
-rw-r--r--sys/netinet6/ip6_input.c11
-rw-r--r--sys/netinet6/nd6.c16
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);
}