Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167318056
D22377.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D22377.diff
View Options
Index: head/sys/fs/nfs/nfs.h
===================================================================
--- head/sys/fs/nfs/nfs.h
+++ head/sys/fs/nfs/nfs.h
@@ -797,6 +797,9 @@
struct mbuf *nfssl_reply;
};
+/* Enumerated type for nfsuserd state. */
+typedef enum { NOTRUNNING=0, STARTSTOP=1, RUNNING=2 } nfsuserd_state;
+
#endif /* _KERNEL */
#endif /* _NFS_NFS_H */
Index: head/sys/fs/nfs/nfs_commonport.c
===================================================================
--- head/sys/fs/nfs/nfs_commonport.c
+++ head/sys/fs/nfs/nfs_commonport.c
@@ -56,7 +56,7 @@
#include <vm/uma.h>
extern int nfscl_ticks;
-extern int nfsrv_nfsuserd;
+extern nfsuserd_state nfsrv_nfsuserd;
extern struct nfssockreq nfsrv_nfsuserdsock;
extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *,
struct thread *);
@@ -774,7 +774,7 @@
break;
case MOD_UNLOAD:
- if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != 0 ||
+ if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != NOTRUNNING ||
nfs_numnfscbd != 0) {
error = EBUSY;
break;
Index: head/sys/fs/nfs/nfs_commonsubs.c
===================================================================
--- head/sys/fs/nfs/nfs_commonsubs.c
+++ head/sys/fs/nfs/nfs_commonsubs.c
@@ -64,7 +64,8 @@
int nfscl_ticks;
int nfsrv_useacl = 1;
struct nfssockreq nfsrv_nfsuserdsock;
-int nfsrv_nfsuserd = 0;
+nfsuserd_state nfsrv_nfsuserd = NOTRUNNING;
+static int nfsrv_userdupcalls = 0;
struct nfsreqhead nfsd_reqq;
uid_t nfsrv_defaultuid = UID_NOBODY;
gid_t nfsrv_defaultgid = GID_NOGROUP;
@@ -3522,18 +3523,22 @@
int error;
NFSLOCKNAMEID();
- if (nfsrv_nfsuserd) {
+ if (nfsrv_nfsuserd != NOTRUNNING) {
NFSUNLOCKNAMEID();
error = EPERM;
goto out;
}
- nfsrv_nfsuserd = 1;
- NFSUNLOCKNAMEID();
+ nfsrv_nfsuserd = STARTSTOP;
/*
* Set up the socket record and connect.
+ * Set nr_client NULL before unlocking, just to ensure that no other
+ * process/thread/core will use a bogus old value. This could only
+ * occur if the use of the nameid lock to protect nfsrv_nfsuserd is
+ * broken.
*/
rp = &nfsrv_nfsuserdsock;
rp->nr_client = NULL;
+ NFSUNLOCKNAMEID();
rp->nr_sotype = SOCK_DGRAM;
rp->nr_soproto = IPPROTO_UDP;
rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST);
@@ -3569,9 +3574,15 @@
rp->nr_vers = RPCNFSUSERD_VERS;
if (error == 0)
error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0);
- if (error) {
+ if (error == 0) {
+ NFSLOCKNAMEID();
+ nfsrv_nfsuserd = RUNNING;
+ NFSUNLOCKNAMEID();
+ } else {
free(rp->nr_nam, M_SONAME);
- nfsrv_nfsuserd = 0;
+ NFSLOCKNAMEID();
+ nfsrv_nfsuserd = NOTRUNNING;
+ NFSUNLOCKNAMEID();
}
out:
NFSEXITCODE(error);
@@ -3586,14 +3597,21 @@
{
NFSLOCKNAMEID();
- if (nfsrv_nfsuserd == 0) {
+ if (nfsrv_nfsuserd != RUNNING) {
NFSUNLOCKNAMEID();
return;
}
- nfsrv_nfsuserd = 0;
+ nfsrv_nfsuserd = STARTSTOP;
+ /* Wait for all upcalls to complete. */
+ while (nfsrv_userdupcalls > 0)
+ msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS,
+ "nfsupcalls", 0);
NFSUNLOCKNAMEID();
newnfs_disconnect(&nfsrv_nfsuserdsock);
free(nfsrv_nfsuserdsock.nr_nam, M_SONAME);
+ NFSLOCKNAMEID();
+ nfsrv_nfsuserd = NOTRUNNING;
+ NFSUNLOCKNAMEID();
}
/*
@@ -3612,12 +3630,19 @@
int error;
NFSLOCKNAMEID();
- if (nfsrv_nfsuserd == 0) {
+ if (nfsrv_nfsuserd != RUNNING) {
NFSUNLOCKNAMEID();
error = EPERM;
goto out;
}
+ /*
+ * Maintain a count of upcalls in progress, so that nfsrv_X()
+ * can wait until no upcalls are in progress.
+ */
+ nfsrv_userdupcalls++;
NFSUNLOCKNAMEID();
+ KASSERT(nfsrv_userdupcalls > 0,
+ ("nfsrv_getuser: non-positive upcalls"));
nd = &nfsd;
cred = newnfs_getcred();
nd->nd_flag = ND_GSSINITREPLY;
@@ -3636,6 +3661,10 @@
}
error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
+ NFSLOCKNAMEID();
+ if (--nfsrv_userdupcalls == 0 && nfsrv_nfsuserd == STARTSTOP)
+ wakeup(&nfsrv_userdupcalls);
+ NFSUNLOCKNAMEID();
NFSFREECRED(cred);
if (!error) {
mbuf_freem(nd->nd_mrep);
Index: head/sys/fs/nfs/nfsport.h
===================================================================
--- head/sys/fs/nfs/nfsport.h
+++ head/sys/fs/nfs/nfsport.h
@@ -669,6 +669,7 @@
#define NFSLOCKSOCK() mtx_lock(&nfs_slock_mutex)
#define NFSUNLOCKSOCK() mtx_unlock(&nfs_slock_mutex)
#define NFSNAMEIDMUTEX extern struct mtx nfs_nameid_mutex
+#define NFSNAMEIDMUTEXPTR (&nfs_nameid_mutex)
#define NFSLOCKNAMEID() mtx_lock(&nfs_nameid_mutex)
#define NFSUNLOCKNAMEID() mtx_unlock(&nfs_nameid_mutex)
#define NFSNAMEIDREQUIRED() mtx_assert(&nfs_nameid_mutex, MA_OWNED)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 21, 9:07 PM (21 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37055535
Default Alt Text
D22377.diff (4 KB)
Attached To
Mode
D22377: fix two races in kernel handling of the nfsuserd daemon
Attached
Detach File
Event Timeline
Log In to Comment