Module Name: src Committed By: snj Date: Sun Nov 8 21:47:45 UTC 2009
Modified Files: src/sys/kern [netbsd-5]: uipc_usrreq.c Log Message: Pull up following revision(s) (requested by bouyer in ticket #932): sys/kern/uipc_usrreq.c: revision 1.127 In uipc_usrreq(PRU_ACCEPT), grab the unp_streamlock before unp_setpeerlocks(). This fixes a race where, for a short period of time, so->so_lock and so2->so_lock are not sync. This makes solocked2() and solocked() unreliable and cause DIAGNOSTIC kernel panics. This also fixes a possible panic in unp_setaddr() which expects the socket locked. Should fix kern/38968, fix proposed in http://mail-index.netbsd.org/tech-kern/2009/08/17/msg005863.html To generate a diff of this commit: cvs rdiff -u -r1.119.4.2 -r1.119.4.3 src/sys/kern/uipc_usrreq.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/uipc_usrreq.c diff -u src/sys/kern/uipc_usrreq.c:1.119.4.2 src/sys/kern/uipc_usrreq.c:1.119.4.3 --- src/sys/kern/uipc_usrreq.c:1.119.4.2 Wed Mar 18 05:33:23 2009 +++ src/sys/kern/uipc_usrreq.c Sun Nov 8 21:47:45 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_usrreq.c,v 1.119.4.2 2009/03/18 05:33:23 snj Exp $ */ +/* $NetBSD: uipc_usrreq.c,v 1.119.4.3 2009/11/08 21:47:45 snj Exp $ */ /*- * Copyright (c) 1998, 2000, 2004, 2008, 2009 The NetBSD Foundation, Inc. @@ -96,7 +96,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.119.4.2 2009/03/18 05:33:23 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.119.4.3 2009/11/08 21:47:45 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -251,6 +251,11 @@ unp->unp_streamlock = NULL; mutex_obj_hold(lock); membar_exit(); + /* + * possible race if lock is not held - see comment in + * uipc_usrreq(PRU_ACCEPT). + */ + KASSERT(mutex_owned(lock)); solockreset(so, lock); solockreset(so2, lock); } @@ -327,6 +332,7 @@ struct unpcb *unp; bool ext; + KASSERT(solocked(so)); unp = sotounpcb(so); ext = false; @@ -443,7 +449,17 @@ * If the connection is fully established, break the * association with uipc_lock and give the connected * pair a seperate lock to share. + * There is a race here: sotounpcb(so2)->unp_streamlock + * is not locked, so when changing so2->so_lock + * another thread can grab it while so->so_lock is still + * pointing to the (locked) uipc_lock. + * this should be harmless, exept that this makes + * solocked2() and solocked() unreliable. + * Another problem is that unp_setaddr() expects the + * the socket locked. Grabing sotounpcb(so2)->unp_streamlock + * fixes both issues. */ + mutex_enter(sotounpcb(so2)->unp_streamlock); unp_setpeerlocks(so2, so); /* * Only now return peer's address, as we may need to @@ -454,6 +470,8 @@ * error == 0 and sun_noname as the peer address. */ unp_setaddr(so, nam, true); + /* so_lock now points to unp_streamlock */ + mutex_exit(so2->so_lock); break; case PRU_SHUTDOWN: