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); } /*