summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-11-22 10:29:40 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-11-22 10:29:40 +0000
commit3c217555afd07546a7e8ab34e0e2479bcf03c897 (patch)
tree411b4552204eae4f05d574ad5f1c079ae0354b43 /sys/kern/uipc_socket.c
parent35462f20f08762826cc9a8f60809f327d1c803d0 (diff)
Enforce that pr_ctloutput is called at IPL_SOFTNET.
This will allow us to keep locking simple as soon as we trade splsoftnet() for a rwlock. ok bluhm@
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 81c6c6d4b5e..552b555c164 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.165 2016/11/21 09:09:06 mpi Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.166 2016/11/22 10:29:39 mpi Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -1541,13 +1541,17 @@ sowwakeup(struct socket *so)
int
sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
{
- int error = 0;
+ int s, error = 0;
struct mbuf *m = m0;
if (level != SOL_SOCKET) {
- if (so->so_proto && so->so_proto->pr_ctloutput)
- return ((*so->so_proto->pr_ctloutput)
- (PRCO_SETOPT, so, level, optname, &m0));
+ if (so->so_proto && so->so_proto->pr_ctloutput) {
+ s = splsoftnet();
+ error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
+ level, optname, &m0);
+ splx(s);
+ return (error);
+ }
error = ENOPROTOOPT;
} else {
switch (optname) {
@@ -1689,8 +1693,11 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
struct domain *dom = so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
- return ((*so->so_proto->pr_ctloutput)
- (PRCO_SETOPT, so, level, optname, &m0));
+ s = splsoftnet();
+ error = (*so->so_proto->pr_ctloutput)
+ (PRCO_SETOPT, so, level, optname, &m0);
+ splx(s);
+ return (error);
}
error = ENOPROTOOPT;
break;
@@ -1718,8 +1725,10 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
break;
}
if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
- (void) ((*so->so_proto->pr_ctloutput)
- (PRCO_SETOPT, so, level, optname, &m0));
+ s = splsoftnet();
+ (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
+ level, optname, &m0);
+ splx(s);
m = NULL; /* freed by protocol */
}
}
@@ -1732,12 +1741,16 @@ bad:
int
sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
{
+ int s, error = 0;
struct mbuf *m;
if (level != SOL_SOCKET) {
if (so->so_proto && so->so_proto->pr_ctloutput) {
- return ((*so->so_proto->pr_ctloutput)
- (PRCO_GETOPT, so, level, optname, mp));
+ s = splsoftnet();
+ error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
+ level, optname, mp);
+ splx(s);
+ return (error);
} else
return (ENOPROTOOPT);
} else {
@@ -1817,8 +1830,11 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
struct domain *dom = so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
- return ((*so->so_proto->pr_ctloutput)
- (PRCO_GETOPT, so, level, optname, mp));
+ s = splsoftnet();
+ error = (*so->so_proto->pr_ctloutput)
+ (PRCO_GETOPT, so, level, optname, mp);
+ splx(s);
+ return (error);
}
return (ENOPROTOOPT);
break;