summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_usrreq.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-02-14 12:22:11 +0000
committerrwatson <rwatson@FreeBSD.org>2007-02-14 12:22:11 +0000
commitc0d4ce5ca7286852d2e2ff41cdd7fdae6d1102f7 (patch)
tree423e12199d7bd0925d85dc97489455e498e15c6b /sys/kern/uipc_usrreq.c
parent59d9c63868cc70ddfa93773887808c29f5214891 (diff)
downloadFreeBSD-src-c0d4ce5ca7286852d2e2ff41cdd7fdae6d1102f7.zip
FreeBSD-src-c0d4ce5ca7286852d2e2ff41cdd7fdae6d1102f7.tar.gz
Change unp_mtx to supporting recursion, and do not drop the unp_mtx over
sonewconn() in unp_connect(). This avoids a race that occurs due to v_socket being an uncounted reference, as the lock was being released in order to call sonewconn(), which otherwise recurses into the UNIX domain socket code via pru_attach, as well as holding the lock over a sleeping memory allocation in uipc_attach(). Switch to a non-sleeping memory allocation during UNIX domain socket attach. This fix non-ideal in that it requires enabling recursion, but is a much smaller change than moving to using true references for v_socket. The reported panic occurs in unp_connect() following the return of sonewconn(). Update copyright year. Panic reported by: jhb
Diffstat (limited to 'sys/kern/uipc_usrreq.c')
-rw-r--r--sys/kern/uipc_usrreq.c18
1 files changed, 5 insertions, 13 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 5238fe5..c418832 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 1982, 1986, 1989, 1991, 1993
* The Regents of the University of California.
- * Copyright (c) 2004-2006 Robert N. M. Watson
+ * Copyright (c) 2004-2007 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -161,7 +161,7 @@ SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
*/
static struct mtx unp_mtx;
#define UNP_LOCK_INIT() \
- mtx_init(&unp_mtx, "unp", NULL, MTX_DEF)
+ mtx_init(&unp_mtx, "unp", NULL, MTX_DEF | MTX_RECURSE)
#define UNP_LOCK() mtx_lock(&unp_mtx)
#define UNP_UNLOCK() mtx_unlock(&unp_mtx)
#define UNP_LOCK_ASSERT() mtx_assert(&unp_mtx, MA_OWNED)
@@ -278,7 +278,7 @@ uipc_attach(struct socket *so, int proto, struct thread *td)
if (error)
return (error);
}
- unp = uma_zalloc(unp_zone, M_WAITOK | M_ZERO);
+ unp = uma_zalloc(unp_zone, M_NOWAIT | M_ZERO);
if (unp == NULL)
return (ENOBUFS);
LIST_INIT(&unp->unp_refs);
@@ -988,17 +988,9 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto bad2;
}
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
- if (so2->so_options & SO_ACCEPTCONN) {
- /*
- * NB: drop locks here so unp_attach is entered w/o
- * locks; this avoids a recursive lock of the head
- * and holding sleep locks across a (potentially)
- * blocking malloc.
- */
- UNP_UNLOCK();
+ if (so2->so_options & SO_ACCEPTCONN)
so3 = sonewconn(so2, 0);
- UNP_LOCK();
- } else
+ else
so3 = NULL;
if (so3 == NULL) {
error = ECONNREFUSED;
OpenPOWER on IntegriCloud