On 21/11/16(Mon) 15:17, Alexander Bluhm wrote:
> [...]
> There are a bunch of calls to sosetopt() in bfd and nfs that are
> not protected by splsoftnet().
Indeed. Then I believe putting the splsoftnet() inside sosetopt() is
a better solution.
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.165
diff -u -p -r1.165 uipc_socket.c
--- kern/uipc_socket.c 21 Nov 2016 09:09:06 -0000 1.165
+++ kern/uipc_socket.c 21 Nov 2016 14:47:01 -0000
@@ -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, i
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, i
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, i
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;