I'd like to enforce that pr_usrreq functions are always called at
IPL_SOFTNET. This will allow us to keep locking simple as soon as
we trade splsoftnet() for a rwlock.
Most of the PRU_* actions are already called under splsoftnet() and
the ones that are not are relatively small, so it should not really
matter since processes are already serialized by the KERNEL_LOCK().
I'd even argue that this is a step forward removing the KERNEL_LOCK
from the socket layer.
Comments, oks?
Index: kern/sys_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_socket.c,v
retrieving revision 1.22
diff -u -p -r1.22 sys_socket.c
--- kern/sys_socket.c 6 Oct 2016 17:02:10 -0000 1.22
+++ kern/sys_socket.c 16 Nov 2016 09:58:54 -0000
@@ -73,6 +73,7 @@ int
soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
{
struct socket *so = (struct socket *)fp->f_data;
+ int s, error = 0;
switch (cmd) {
@@ -122,8 +123,12 @@ soo_ioctl(struct file *fp, u_long cmd, c
return (ifioctl(so, cmd, data, p));
if (IOCGROUP(cmd) == 'r')
return (rtioctl(cmd, data, p));
- return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
+ s = splsoftnet();
+ error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
(struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p));
+ splx(s);
+
+ return (error);
}
int
@@ -167,6 +172,7 @@ int
soo_stat(struct file *fp, struct stat *ub, struct proc *p)
{
struct socket *so = fp->f_data;
+ int s;
memset(ub, 0, sizeof (*ub));
ub->st_mode = S_IFSOCK;
@@ -177,8 +183,10 @@ soo_stat(struct file *fp, struct stat *u
ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
ub->st_uid = so->so_euid;
ub->st_gid = so->so_egid;
+ s = splsoftnet();
(void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
(struct mbuf *)ub, NULL, NULL, p));
+ splx(s);
return (0);
}
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.164
diff -u -p -r1.164 uipc_socket.c
--- kern/uipc_socket.c 14 Nov 2016 08:45:30 -0000 1.164
+++ kern/uipc_socket.c 16 Nov 2016 10:14:05 -0000
@@ -652,8 +652,10 @@ soreceive(struct socket *so, struct mbuf
flags |= MSG_DONTWAIT;
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
+ s = splsoftnet();
error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
(struct mbuf *)(long)(flags & MSG_PEEK), NULL, curproc);
+ splx(s);
if (error)
goto bad;
do {
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.139
diff -u -p -r1.139 uipc_syscalls.c
--- kern/uipc_syscalls.c 9 Nov 2016 09:39:43 -0000 1.139
+++ kern/uipc_syscalls.c 16 Nov 2016 10:17:08 -0000
@@ -1066,7 +1066,7 @@ sys_getsockname(struct proc *p, void *v,
struct socket *so;
struct mbuf *m = NULL;
socklen_t len;
- int error;
+ int error, s;
if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
return (error);
@@ -1078,14 +1078,15 @@ sys_getsockname(struct proc *p, void *v,
if (error)
goto bad;
m = m_getclr(M_WAIT, MT_SONAME);
+ s = splsoftnet();
error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
+ splx(s);
if (error)
goto bad;
error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
bad:
FRELE(fp, p);
- if (m)
- m_freem(m);
+ m_freem(m);
return (error);
}
@@ -1104,7 +1105,7 @@ sys_getpeername(struct proc *p, void *v,
struct socket *so;
struct mbuf *m = NULL;
socklen_t len;
- int error;
+ int error, s;
if ((error = getsock(p, SCARG(uap, fdes), &fp)) != 0)
return (error);
@@ -1120,7 +1121,9 @@ sys_getpeername(struct proc *p, void *v,
if (error)
goto bad;
m = m_getclr(M_WAIT, MT_SONAME);
+ s = splsoftnet();
error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
+ splx(s);
if (error)
goto bad;
error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.461
diff -u -p -r1.461 if.c
--- net/if.c 14 Nov 2016 10:52:04 -0000 1.461
+++ net/if.c 16 Nov 2016 09:58:54 -0000
@@ -2046,9 +2046,11 @@ ifioctl(struct socket *so, u_long cmd, c
default:
if (so->so_proto == 0)
return (EOPNOTSUPP);
+ s = splsoftnet();
error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
(struct mbuf *) cmd, (struct mbuf *) data,
(struct mbuf *) ifp, p));
+ splx(s);
break;
}
Index: net/raw_usrreq.c
===================================================================
RCS file: /cvs/src/sys/net/raw_usrreq.c,v
retrieving revision 1.25
diff -u -p -r1.25 raw_usrreq.c
--- net/raw_usrreq.c 8 Oct 2016 03:32:25 -0000 1.25
+++ net/raw_usrreq.c 16 Nov 2016 09:58:54 -0000
@@ -137,7 +137,9 @@ raw_usrreq(struct socket *so, int req, s
{
struct rawcb *rp = sotorawcb(so);
int error = 0;
- int len, s;
+ int len;
+
+ splsoftassert(IPL_SOFTNET);
if (req == PRU_CONTROL)
return (EOPNOTSUPP);
@@ -149,7 +151,6 @@ raw_usrreq(struct socket *so, int req, s
m_freem(m);
return (EINVAL);
}
- s = splsoftnet();
switch (req) {
/*
@@ -230,7 +231,6 @@ raw_usrreq(struct socket *so, int req, s
/*
* stat: don't bother with a blocksize.
*/
- splx(s);
return (0);
/*
@@ -238,7 +238,6 @@ raw_usrreq(struct socket *so, int req, s
*/
case PRU_RCVOOB:
case PRU_RCVD:
- splx(s);
return (EOPNOTSUPP);
case PRU_LISTEN:
@@ -270,7 +269,6 @@ raw_usrreq(struct socket *so, int req, s
default:
panic("raw_usrreq");
}
- splx(s);
m_freem(m);
return (error);
}
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.208
diff -u -p -r1.208 rtsock.c
--- net/rtsock.c 18 Oct 2016 11:05:45 -0000 1.208
+++ net/rtsock.c 16 Nov 2016 09:58:54 -0000
@@ -149,10 +149,11 @@ route_usrreq(struct socket *so, int req,
{
struct rawcb *rp;
struct routecb *rop;
- int s, af;
+ int af;
int error = 0;
- s = splsoftnet();
+ splsoftassert(IPL_SOFTNET);
+
rp = sotorawcb(so);
switch (req) {
@@ -178,7 +179,6 @@ route_usrreq(struct socket *so, int req,
error = raw_attach(so, (int)(long)nam);
if (error) {
free(rop, M_PCB, sizeof(struct routecb));
- splx(s);
return (error);
}
rop->rtableid = curproc->p_p->ps_rtableid;
@@ -229,7 +229,6 @@ route_usrreq(struct socket *so, int req,
error = raw_usrreq(so, req, m, nam, control, p);
}
- splx(s);
return (error);
}
Index: netinet/ip_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.39
diff -u -p -r1.39 ip_divert.c
--- netinet/ip_divert.c 7 Mar 2016 18:44:00 -0000 1.39
+++ netinet/ip_divert.c 16 Nov 2016 09:58:54 -0000
@@ -63,7 +63,6 @@ int divbhashsize = DIVERTHASHSIZE;
static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
-void divert_detach(struct inpcb *);
int divert_output(struct inpcb *, struct mbuf *, struct mbuf *,
struct mbuf *);
void
@@ -248,7 +247,8 @@ divert_usrreq(struct socket *so, int req
{
struct inpcb *inp = sotoinpcb(so);
int error = 0;
- int s;
+
+ splsoftassert(IPL_SOFTNET);
if (req == PRU_CONTROL) {
return (in_control(so, (u_long)m, (caddr_t)addr,
@@ -269,9 +269,7 @@ divert_usrreq(struct socket *so, int req
error = EACCES;
break;
}
- s = splsoftnet();
error = in_pcballoc(so, &divbtable);
- splx(s);
if (error)
break;
@@ -282,13 +280,11 @@ divert_usrreq(struct socket *so, int req
break;
case PRU_DETACH:
- divert_detach(inp);
+ in_pcbdetach(inp);
break;
case PRU_BIND:
- s = splsoftnet();
error = in_pcbbind(inp, addr, p);
- splx(s);
break;
case PRU_SHUTDOWN:
@@ -300,7 +296,7 @@ divert_usrreq(struct socket *so, int req
case PRU_ABORT:
soisdisconnected(so);
- divert_detach(inp);
+ in_pcbdetach(inp);
break;
case PRU_SOCKADDR:
@@ -339,15 +335,6 @@ release:
m_freem(control);
m_freem(m);
return (error);
-}
-
-void
-divert_detach(struct inpcb *inp)
-{
- int s = splsoftnet();
-
- in_pcbdetach(inp);
- splx(s);
}
/*
Index: netinet/raw_ip.c
===================================================================
RCS file: /cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.87
diff -u -p -r1.87 raw_ip.c
--- netinet/raw_ip.c 14 Nov 2016 03:51:53 -0000 1.87
+++ netinet/raw_ip.c 16 Nov 2016 09:58:54 -0000
@@ -409,7 +409,8 @@ rip_usrreq(struct socket *so, int req, s
{
struct inpcb *inp = sotoinpcb(so);
int error = 0;
- int s;
+
+ splsoftassert(IPL_SOFTNET);
if (req == PRU_CONTROL)
return (in_control(so, (u_long)m, (caddr_t)nam,
@@ -433,13 +434,10 @@ rip_usrreq(struct socket *so, int req, s
error = EPROTONOSUPPORT;
break;
}
- s = splsoftnet();
if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
(error = in_pcballoc(so, &rawcbtable))) {
- splx(s);
break;
}
- splx(s);
inp = sotoinpcb(so);
inp->inp_ip.ip_p = (long)nam;
break;
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.135
diff -u -p -r1.135 tcp_usrreq.c
--- netinet/tcp_usrreq.c 24 Sep 2016 14:51:37 -0000 1.135
+++ netinet/tcp_usrreq.c 16 Nov 2016 09:58:54 -0000
@@ -130,10 +130,11 @@ tcp_usrreq(struct socket *so, int req, s
struct sockaddr_in *sin;
struct inpcb *inp;
struct tcpcb *tp = NULL;
- int s;
int error = 0;
short ostate;
+ splsoftassert(IPL_SOFTNET);
+
if (req == PRU_CONTROL) {
#ifdef INET6
if (sotopf(so) == PF_INET6)
@@ -150,7 +151,6 @@ tcp_usrreq(struct socket *so, int req, s
return (EINVAL);
}
- s = splsoftnet();
inp = sotoinpcb(so);
/*
* When a TCP is attached to a socket, then there will be
@@ -161,7 +161,6 @@ tcp_usrreq(struct socket *so, int req, s
error = so->so_error;
if (error == 0)
error = EINVAL;
- splx(s);
/*
* The following corrects an mbuf leak under rare
* circumstances
@@ -174,7 +173,6 @@ tcp_usrreq(struct socket *so, int req, s
tp = intotcpcb(inp);
/* tp might get 0 when using socket splicing */
if (tp == NULL) {
- splx(s);
return (0);
}
#ifdef KPROF
@@ -382,7 +380,6 @@ tcp_usrreq(struct socket *so, int req, s
case PRU_SENSE:
((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
- splx(s);
return (0);
case PRU_RCVOOB:
@@ -447,7 +444,6 @@ tcp_usrreq(struct socket *so, int req, s
}
if (tp && (so->so_options & SO_DEBUG))
tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);
- splx(s);
return (error);
}
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.220
diff -u -p -r1.220 udp_usrreq.c
--- netinet/udp_usrreq.c 3 Nov 2016 18:42:35 -0000 1.220
+++ netinet/udp_usrreq.c 16 Nov 2016 09:58:54 -0000
@@ -1105,7 +1105,8 @@ udp_usrreq(struct socket *so, int req, s
{
struct inpcb *inp;
int error = 0;
- int s;
+
+ splsoftassert(IPL_SOFTNET);
if (req == PRU_CONTROL) {
#ifdef INET6
@@ -1118,7 +1119,6 @@ udp_usrreq(struct socket *so, int req, s
(struct ifnet *)control));
}
- s = splsoftnet();
inp = sotoinpcb(so);
if (inp == NULL && req != PRU_ATTACH) {
error = EINVAL;
@@ -1255,7 +1255,6 @@ udp_usrreq(struct socket *so, int req, s
else
#endif
error = udp_output(inp, m, addr, control);
- splx(s);
return (error);
case PRU_ABORT:
@@ -1289,7 +1288,6 @@ udp_usrreq(struct socket *so, int req, s
* Perhaps Path MTU might be returned for a connected
* UDP socket in this case.
*/
- splx(s);
return (0);
case PRU_SENDOOB:
@@ -1302,7 +1300,6 @@ udp_usrreq(struct socket *so, int req, s
case PRU_RCVD:
case PRU_RCVOOB:
- splx(s);
return (EOPNOTSUPP); /* do not free mbuf's */
default:
@@ -1310,7 +1307,6 @@ udp_usrreq(struct socket *so, int req, s
}
release:
- splx(s);
m_freem(control);
m_freem(m);
return (error);
Index: netinet6/ip6_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.41
diff -u -p -r1.41 ip6_divert.c
--- netinet6/ip6_divert.c 29 Mar 2016 11:57:51 -0000 1.41
+++ netinet6/ip6_divert.c 16 Nov 2016 09:58:54 -0000
@@ -64,7 +64,6 @@ int divb6hashsize = DIVERTHASHSIZE;
static struct sockaddr_in6 ip6addr = { sizeof(ip6addr), AF_INET6 };
-void divert6_detach(struct inpcb *);
int divert6_output(struct inpcb *, struct mbuf *, struct mbuf *,
struct mbuf *);
@@ -251,7 +250,8 @@ divert6_usrreq(struct socket *so, int re
{
struct inpcb *inp = sotoinpcb(so);
int error = 0;
- int s;
+
+ splsoftassert(IPL_SOFTNET);
if (req == PRU_CONTROL) {
return (in6_control(so, (u_long)m, (caddr_t)addr,
@@ -272,9 +272,7 @@ divert6_usrreq(struct socket *so, int re
error = EACCES;
break;
}
- s = splsoftnet();
error = in_pcballoc(so, &divb6table);
- splx(s);
if (error)
break;
@@ -285,13 +283,11 @@ divert6_usrreq(struct socket *so, int re
break;
case PRU_DETACH:
- divert6_detach(inp);
+ in_pcbdetach(inp);
break;
case PRU_BIND:
- s = splsoftnet();
error = in_pcbbind(inp, addr, p);
- splx(s);
break;
case PRU_SHUTDOWN:
@@ -303,7 +299,7 @@ divert6_usrreq(struct socket *so, int re
case PRU_ABORT:
soisdisconnected(so);
- divert6_detach(inp);
+ in_pcbdetach(inp);
break;
case PRU_SOCKADDR:
@@ -342,15 +338,6 @@ release:
m_freem(control);
m_freem(m);
return (error);
-}
-
-void
-divert6_detach(struct inpcb *inp)
-{
- int s = splsoftnet();
-
- in_pcbdetach(inp);
- splx(s);
}
/*
Index: netinet6/raw_ip6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.98
diff -u -p -r1.98 raw_ip6.c
--- netinet6/raw_ip6.c 25 Oct 2016 19:40:57 -0000 1.98
+++ netinet6/raw_ip6.c 16 Nov 2016 09:58:54 -0000
@@ -568,9 +568,10 @@ rip6_usrreq(struct socket *so, int req,
{
struct inpcb *in6p = sotoinpcb(so);
int error = 0;
- int s;
int priv;
+ splsoftassert(IPL_SOFTNET);
+
priv = 0;
if ((so->so_state & SS_PRIV) != 0)
priv++;
@@ -591,13 +592,10 @@ rip6_usrreq(struct socket *so, int req,
error = EPROTONOSUPPORT;
break;
}
- s = splsoftnet();
if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) ||
(error = in_pcballoc(so, &rawin6pcbtable))) {
- splx(s);
break;
}
- splx(s);
in6p = sotoinpcb(so);
in6p->inp_ipv6.ip6_nxt = (long)nam;
in6p->inp_cksum6 = -1;