diff options
author | 2016-12-20 18:33:43 +0000 | |
---|---|---|
committer | 2016-12-20 18:33:43 +0000 | |
commit | 4eb8db84bc9d6a660b66b3f79301db47bc24b926 (patch) | |
tree | 0ccaf106b2bfb5c91eb9a0858f2bd9eae444e8c1 /sys/kern/uipc_domain.c | |
parent | In midiread() and midiwrite(), add a second goto label to (diff) | |
download | wireguard-openbsd-4eb8db84bc9d6a660b66b3f79301db47bc24b926.tar.xz wireguard-openbsd-4eb8db84bc9d6a660b66b3f79301db47bc24b926.zip |
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/kern/uipc_domain.c')
-rw-r--r-- | sys/kern/uipc_domain.c | 24 |
1 files changed, 16 insertions, 8 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); } |