diff options
author | rwatson <rwatson@FreeBSD.org> | 2007-02-14 12:22:11 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2007-02-14 12:22:11 +0000 |
commit | c0d4ce5ca7286852d2e2ff41cdd7fdae6d1102f7 (patch) | |
tree | 423e12199d7bd0925d85dc97489455e498e15c6b /sys/kern/uipc_usrreq.c | |
parent | 59d9c63868cc70ddfa93773887808c29f5214891 (diff) | |
download | FreeBSD-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.c | 18 |
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; |