Module Name:    src
Committed By:   snj
Date:           Mon Apr 13 21:21:31 UTC 2009

Modified Files:
        src/sys/nfs [netbsd-5]: nfs_syscalls.c

Log Message:
Pull up following revision(s) (requested by ad in ticket #701):
        sys/nfs/nfs_syscalls.c: revision 1.147
PR kern/41154: possible races in NFS server code
Fix some of the races (but probably not all of them) in the NFS server code.
nfssvc_nfsd(): change a splsoftclock()/spx() to mutex_enter/exit(&nfsd_lock)
 (I guess it was forgotten when the nfsd code was made SMP safe)
m_freem(nd_nam) in nfsrv_slpderef() instead of nfsrv_zapsock() to
 avoid possible use after free in nfssvc_nfsd()
Fix nfsrv_slpderef() to not release  nfsd_lock before testing SLP_VALID
 and reaquiring it just after. This could cause a use after free
 of the slp if one thread is in nfsrv_slpderef() and the other one grabs
 slp from nfssvc_sockpending and zap it.


To generate a diff of this commit:
cvs rdiff -u -r1.140 -r1.140.4.1 src/sys/nfs/nfs_syscalls.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/nfs/nfs_syscalls.c
diff -u src/sys/nfs/nfs_syscalls.c:1.140 src/sys/nfs/nfs_syscalls.c:1.140.4.1
--- src/sys/nfs/nfs_syscalls.c:1.140	Thu Oct  9 14:38:21 2008
+++ src/sys/nfs/nfs_syscalls.c	Mon Apr 13 21:21:30 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_syscalls.c,v 1.140 2008/10/09 14:38:21 christos Exp $	*/
+/*	$NetBSD: nfs_syscalls.c,v 1.140.4.1 2009/04/13 21:21:30 snj Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.140 2008/10/09 14:38:21 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.140.4.1 2009/04/13 21:21:30 snj Exp $");
 
 #include "fs_nfs.h"
 #include "opt_nfs.h"
@@ -511,7 +511,6 @@
 	u_quad_t cur_usec;
 	int error = 0, cacherep, siz, sotype, writes_todo;
 	struct proc *p = l->l_proc;
-	int s;
 	bool doreinit;
 
 #ifndef nolint
@@ -761,14 +760,14 @@
 			getmicrotime(&tv);
 			cur_usec = (u_quad_t)tv.tv_sec * 1000000 +
 			    (u_quad_t)tv.tv_usec;
-			s = splsoftclock();
+			mutex_enter(&nfsd_lock);
 			if (LIST_FIRST(&slp->ns_tq) &&
 			    LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) {
 				cacherep = RC_DOIT;
 				writes_todo = 1;
 			} else
 				writes_todo = 0;
-			splx(s);
+			mutex_exit(&nfsd_lock);
 		} while (writes_todo);
 		if (nfsrv_dorec(slp, nfsd, &nd, &dummy)) {
 			nfsd->nfsd_slp = NULL;
@@ -828,8 +827,6 @@
 	soshutdown(so, SHUT_RDWR);
 	sounlock(so);
 
-	if (slp->ns_nam)
-		m_free(slp->ns_nam);
 	m_freem(slp->ns_raw);
 	m = slp->ns_rec;
 	while (m != NULL) {
@@ -839,6 +836,7 @@
 		m_freem(m);
 		m = n;
 	}
+	/* XXX what about freeing ns_frag ? */
 	for (nuidp = TAILQ_FIRST(&slp->ns_uidlruhead); nuidp != 0;
 	    nuidp = nnuidp) {
 		nnuidp = TAILQ_NEXT(nuidp, nu_lru);
@@ -871,11 +869,9 @@
 	mutex_enter(&nfsd_lock);
 	KASSERT(slp->ns_sref > 0);
 	ref = --slp->ns_sref;
-	mutex_exit(&nfsd_lock);
 	if (ref == 0 && (slp->ns_flags & SLP_VALID) == 0) {
 		file_t *fp;
 
-		mutex_enter(&nfsd_lock);
 		KASSERT((slp->ns_gflags & SLP_G_DOREC) == 0);
 		TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
 		mutex_exit(&nfsd_lock);
@@ -889,9 +885,12 @@
 			closef(fp);
 			slp->ns_so = NULL;
 		}
-
+		
+		if (slp->ns_nam)
+			m_free(slp->ns_nam);
 		nfsrv_sockfree(slp);
-	}
+	} else
+		mutex_exit(&nfsd_lock);
 }
 
 /*

Reply via email to