summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_usrreq.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-06-18 20:56:22 +0000
committerjhb <jhb@FreeBSD.org>2009-06-18 20:56:22 +0000
commitb74ac99a510b71d1e4f9b640cf1f084052e00d45 (patch)
tree90162d4bd71f58d1046f15655d9a3a0f301a7a9a /sys/kern/uipc_usrreq.c
parentf3a1b951fc132d7220b5d5bdb2890f68143a229f (diff)
downloadFreeBSD-src-b74ac99a510b71d1e4f9b640cf1f084052e00d45.zip
FreeBSD-src-b74ac99a510b71d1e4f9b640cf1f084052e00d45.tar.gz
Fix a deadlock in the getpeername() method for UNIX domain sockets.
Instead of locking the local unp followed by the remote unp, use the same locking model as accept() and read lock the global link lock followed by the remote unp while fetching the remote sockaddr. Reported by: Mel Flynn mel.flynn of mailing.thruhere.net Reviewed by: rwatson MFC after: 1 week
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r--sys/kern/uipc_usrreq.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index a8fe7ca..aadebb0 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -671,7 +671,7 @@ uipc_peeraddr(struct socket *so, struct sockaddr **nam)
KASSERT(unp != NULL, ("uipc_peeraddr: unp == NULL"));
*nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
- UNP_PCB_LOCK(unp);
+ UNP_LINK_RLOCK();
/*
* XXX: It seems that this test always fails even when connection is
* established. So, this else clause is added as workaround to
@@ -681,7 +681,7 @@ uipc_peeraddr(struct socket *so, struct sockaddr **nam)
if (unp2 != NULL) {
UNP_PCB_LOCK(unp2);
if (unp2->unp_addr != NULL)
- sa = (struct sockaddr *) unp->unp_conn->unp_addr;
+ sa = (struct sockaddr *) unp2->unp_addr;
else
sa = &sun_noname;
bcopy(sa, *nam, sa->sa_len);
@@ -690,7 +690,7 @@ uipc_peeraddr(struct socket *so, struct sockaddr **nam)
sa = &sun_noname;
bcopy(sa, *nam, sa->sa_len);
}
- UNP_PCB_UNLOCK(unp);
+ UNP_LINK_RUNLOCK();
return (0);
}
@@ -850,7 +850,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
* return the slightly counter-intuitive but otherwise
* correct error that the socket is not connected.
*
- * Locking here must be done carefully: the inkage lock
+ * Locking here must be done carefully: the linkage lock
* prevents interconnections between unpcbs from changing, so
* we can traverse from unp to unp2 without acquiring unp's
* lock. Socket buffer locks follow unpcb locks, so we can
OpenPOWER on IntegriCloud