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