From bb797f408613b46cee97b8cac9de83beb3e39876 Mon Sep 17 00:00:00 2001 From: Martin Pieuchot Date: Mon, 21 Nov 2016 09:09:07 +0000 Subject: Enforce that pr_usrreq functions are called at IPL_SOFTNET. This will allow us to keep locking simple as soon as we trade splsoftnet() for a rwlock. ok bluhm@, claudio@ --- sys/kern/sys_socket.c | 12 ++++++++++-- sys/kern/uipc_socket.c | 4 +++- sys/kern/uipc_syscalls.c | 13 ++++++++----- sys/net/if.c | 4 +++- sys/net/raw_usrreq.c | 10 ++++------ sys/net/rtsock.c | 9 ++++----- sys/netinet/ip_divert.c | 23 +++++------------------ sys/netinet/raw_ip.c | 8 +++----- sys/netinet/tcp_usrreq.c | 10 +++------- sys/netinet/udp_usrreq.c | 10 +++------- sys/netinet6/ip6_divert.c | 23 +++++------------------ sys/netinet6/raw_ip6.c | 8 +++----- 12 files changed, 54 insertions(+), 80 deletions(-) diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index 7a90f780067..1ed6dff439c 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_socket.c,v 1.22 2016/10/06 17:02:10 bluhm Exp $ */ +/* $OpenBSD: sys_socket.c,v 1.23 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */ /* @@ -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, caddr_t data, struct proc *p) 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 *ub, struct proc *p) 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); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 12edabecfbd..81c6c6d4b5e 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.164 2016/11/14 08:45:30 mpi Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.165 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -652,8 +652,10 @@ soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, 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 { diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 3ae8670b0e0..5dc464e863c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.139 2016/11/09 09:39:43 mpi Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.140 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -1066,7 +1066,7 @@ sys_getsockname(struct proc *p, void *v, register_t *retval) 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, register_t *retval) 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, register_t *retval) 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, register_t *retval) 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)); diff --git a/sys/net/if.c b/sys/net/if.c index 02e5433a20f..1e6d190dc81 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.461 2016/11/14 10:52:04 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.462 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -2046,9 +2046,11 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) 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; } diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index d17ea931ad0..837c1f0901a 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_usrreq.c,v 1.25 2016/10/08 03:32:25 claudio Exp $ */ +/* $OpenBSD: raw_usrreq.c,v 1.26 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: raw_usrreq.c,v 1.11 1996/02/13 22:00:43 christos Exp $ */ /* @@ -137,7 +137,9 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, { 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, struct mbuf *m, struct mbuf *nam, m_freem(m); return (EINVAL); } - s = splsoftnet(); switch (req) { /* @@ -230,7 +231,6 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, /* * stat: don't bother with a blocksize. */ - splx(s); return (0); /* @@ -238,7 +238,6 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, */ case PRU_RCVOOB: case PRU_RCVD: - splx(s); return (EOPNOTSUPP); case PRU_LISTEN: @@ -270,7 +269,6 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, default: panic("raw_usrreq"); } - splx(s); m_freem(m); return (error); } diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 46150c61310..8953a30a60b 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.208 2016/10/18 11:05:45 bluhm Exp $ */ +/* $OpenBSD: rtsock.c,v 1.209 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -149,10 +149,11 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, { 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, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, error = raw_usrreq(so, req, m, nam, control, p); } - splx(s); return (error); } diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index c737fbbe93c..e660b79a2f2 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_divert.c,v 1.39 2016/03/07 18:44:00 naddy Exp $ */ +/* $OpenBSD: ip_divert.c,v 1.40 2016/11/21 09:09:06 mpi Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -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 mbuf *m, struct mbuf *addr, { 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, struct mbuf *m, struct mbuf *addr, 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, struct mbuf *m, struct mbuf *addr, 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, struct mbuf *m, struct mbuf *addr, case PRU_ABORT: soisdisconnected(so); - divert_detach(inp); + in_pcbdetach(inp); break; case PRU_SOCKADDR: @@ -341,15 +337,6 @@ release: return (error); } -void -divert_detach(struct inpcb *inp) -{ - int s = splsoftnet(); - - in_pcbdetach(inp); - splx(s); -} - /* * Sysctl for divert variables. */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 147d6266e79..34c307c1215 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.87 2016/11/14 03:51:53 dlg Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.88 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -409,7 +409,8 @@ rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, { 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, struct mbuf *m, struct mbuf *nam, 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; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index a530575f07b..5b5f724022c 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.135 2016/09/24 14:51:37 naddy Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.136 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -130,10 +130,11 @@ tcp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, 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, struct mbuf *m, struct mbuf *nam, } if (tp && (so->so_options & SO_DEBUG)) tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0); - splx(s); return (error); } diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 957f01a595f..83d96cc84b0 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.221 2016/11/18 02:53:47 dlg Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.222 2016/11/21 09:09:06 mpi Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -1107,7 +1107,8 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, { struct inpcb *inp; int error = 0; - int s; + + splsoftassert(IPL_SOFTNET); if (req == PRU_CONTROL) { #ifdef INET6 @@ -1120,7 +1121,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, (struct ifnet *)control)); } - s = splsoftnet(); inp = sotoinpcb(so); if (inp == NULL && req != PRU_ATTACH) { error = EINVAL; @@ -1257,7 +1257,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, else #endif error = udp_output(inp, m, addr, control); - splx(s); return (error); case PRU_ABORT: @@ -1291,7 +1290,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, * Perhaps Path MTU might be returned for a connected * UDP socket in this case. */ - splx(s); return (0); case PRU_SENDOOB: @@ -1304,7 +1302,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, case PRU_RCVD: case PRU_RCVOOB: - splx(s); return (EOPNOTSUPP); /* do not free mbuf's */ default: @@ -1312,7 +1309,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, } release: - splx(s); m_freem(control); m_freem(m); return (error); diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c index 4a5f61de24f..42bea1ad86b 100644 --- a/sys/netinet6/ip6_divert.c +++ b/sys/netinet6/ip6_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_divert.c,v 1.41 2016/03/29 11:57:51 chl Exp $ */ +/* $OpenBSD: ip6_divert.c,v 1.42 2016/11/21 09:09:06 mpi Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -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 req, struct mbuf *m, struct mbuf *addr, { 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 req, struct mbuf *m, struct mbuf *addr, 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 req, struct mbuf *m, struct mbuf *addr, 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 req, struct mbuf *m, struct mbuf *addr, case PRU_ABORT: soisdisconnected(so); - divert6_detach(inp); + in_pcbdetach(inp); break; case PRU_SOCKADDR: @@ -344,15 +340,6 @@ release: return (error); } -void -divert6_detach(struct inpcb *inp) -{ - int s = splsoftnet(); - - in_pcbdetach(inp); - splx(s); -} - /* * Sysctl for divert variables. */ diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 69c96a4f7b3..d0512dac18e 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.98 2016/10/25 19:40:57 florian Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.99 2016/11/21 09:09:06 mpi Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -568,9 +568,10 @@ rip6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, { 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, struct mbuf *m, struct mbuf *nam, 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; -- cgit v1.2.3