diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-12-29 07:35:10 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-12-29 07:35:10 +0000 |
commit | 7f580a7e15408fd9f7aab67ee05141cffcb972ee (patch) | |
tree | 76785fb98297ca50024d1b668c4b3ef6a284f435 /sys/kern/uipc_usrreq.c | |
parent | 93adc4764985264684268ebe6c1f8af111603968 (diff) |
Release the NET_LOCK() before calling unp_connect(). It is not possible
to hold it during VFS operations as NFS might try to grab it.
Problem also reported by Siegfried Rudzio on bugs@.
ok visa@
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 34 |
1 files changed, 15 insertions, 19 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 7f5b2abfe14..96d19b95608 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.107 2016/12/22 15:15:28 mpi Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.108 2016/12/29 07:35:09 mpi Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -143,7 +143,10 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, break; case PRU_CONNECT: + /* XXXSMP breaks atomicity */ + rw_exit_write(&netlock); error = unp_connect(so, nam, p); + rw_enter_write(&netlock); break; case PRU_CONNECT2: @@ -211,7 +214,10 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EISCONN; break; } + /* XXXSMP breaks atomicity */ + rw_exit_write(&netlock); error = unp_connect(so, nam, p); + rw_enter_write(&netlock); if (error) break; } else { @@ -485,8 +491,10 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) struct vnode *vp; struct socket *so2, *so3; struct unpcb *unp, *unp2, *unp3; - int error; struct nameidata nd; + int error, s; + + rw_assert_unlocked(&netlock); if (soun->sun_family != AF_UNIX) return (EAFNOSUPPORT); @@ -500,22 +508,7 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, soun->sun_path, p); nd.ni_pledge = PLEDGE_UNIX; - /* - * XXXSMP breaks atomicity - * - * NFS might try to enter sosend(), at least during boot: - * sosend - * nfs_send - * nfs_request - * nfs_lookup - * VOP_LOOKUP - * vfs_lookup - * namei - */ - rw_exit_write(&netlock); - error = namei(&nd); - rw_enter_write(&netlock); - if (error != 0) + if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp->v_type != VSOCK) { @@ -533,11 +526,12 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) error = EPROTOTYPE; goto bad; } + NET_LOCK(s); if (so->so_proto->pr_flags & PR_CONNREQUIRED) { if ((so2->so_options & SO_ACCEPTCONN) == 0 || (so3 = sonewconn(so2, 0)) == 0) { error = ECONNREFUSED; - goto bad; + goto unlock; } unp = sotounpcb(so); unp2 = sotounpcb(so2); @@ -556,6 +550,8 @@ unp_connect(struct socket *so, struct mbuf *nam, struct proc *p) } } error = unp_connect2(so, so2); +unlock: + NET_UNLOCK(s); bad: vput(vp); return (error); |