summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_usrreq.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-12-29 07:35:10 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-12-29 07:35:10 +0000
commit7f580a7e15408fd9f7aab67ee05141cffcb972ee (patch)
tree76785fb98297ca50024d1b668c4b3ef6a284f435 /sys/kern/uipc_usrreq.c
parent93adc4764985264684268ebe6c1f8af111603968 (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.c34
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);