Index: linux/fs/nfsd/auth.c
diff -u linux/fs/nfsd/auth.c:1.1 linux/fs/nfsd/auth.c:1.1.2.1
--- linux/fs/nfsd/auth.c:1.1	Fri Oct 16 12:08:05 1998
+++ linux/fs/nfsd/auth.c	Mon Oct 26 22:21:59 1998
@@ -43,5 +43,14 @@
 		current->fsgid = exp->ex_anon_gid;
 	for (i = 0; i < NGROUPS; i++)
 		current->groups[i] = cred->cr_groups[i];
+
+	if ((cred->cr_uid)) {
+		cap_lower(current->cap_effective, CAP_DAC_OVERRIDE);
+		cap_lower(current->cap_effective, CAP_DAC_READ_SEARCH);
+	} else {
+		cap_raise(current->cap_effective, CAP_DAC_OVERRIDE);
+		cap_raise(current->cap_effective, CAP_DAC_READ_SEARCH);
+	}
+
 	rqstp->rq_userset = 1;
 }
Index: linux/fs/nfsd/export.c
diff -u linux/fs/nfsd/export.c:1.5 linux/fs/nfsd/export.c:1.1.2.9
--- linux/fs/nfsd/export.c:1.5	Sat Oct 24 11:36:37 1998
+++ linux/fs/nfsd/export.c	Fri Oct 23 10:22:54 1998
@@ -457,14 +457,17 @@
 	   char *path, struct knfs_fh *f)
 {
 	struct svc_export	*exp;
-	struct dentry		*dentry;
+	struct dentry		*dentry = NULL;
 	struct inode		*inode;
 	struct svc_fh		fh;
 	int			err;
 
+	err = -EPERM;
 	if (path) {
-		dentry = lookup_dentry(path, NULL, 0);
-
+		if (!(dentry = lookup_dentry(path, NULL, 0))) {
+			printk("nfsd: exp_rootfh path not found %s", path);
+			return -EPERM;
+		}
 		dev = dentry->d_inode->i_dev;
 		ino = dentry->d_inode->i_ino;
 	
@@ -474,17 +477,21 @@
 	} else {
 		dprintk("nfsd: exp_rootfh(%s:%x/%ld)\n",
 		         clp->cl_ident, dev, ino);
-		exp = exp_get(clp, dev, ino);
-		dentry = dget(exp->ex_dentry);
+		if ((exp = exp_get(clp, dev, ino)))
+			if (!(dentry = dget(exp->ex_dentry))) {
+				printk("exp_rootfh: Aieee, NULL dentry\n");
+				return -EPERM;
+			}
 	}
-	err = -EPERM;
-	if (!exp)
+	if (!exp) {
+		dprintk("nfsd: exp_rootfh export not found.\n");
 		goto out;
+	}
 
 	inode = dentry->d_inode;
 	if (!inode) {
 		printk("exp_rootfh: Aieee, NULL d_inode\n");
-		return -EPERM;
+		goto out;
 	}
 	if (inode->i_dev != dev || inode->i_ino != ino) {
 		printk("exp_rootfh: Aieee, ino/dev mismatch\n");
Index: linux/fs/nfsd/nfsfh.c
diff -u linux/fs/nfsd/nfsfh.c:1.2 linux/fs/nfsd/nfsfh.c:1.1.2.6
--- linux/fs/nfsd/nfsfh.c:1.2	Sat Oct 24 11:36:37 1998
+++ linux/fs/nfsd/nfsfh.c	Mon Oct 26 23:25:40 1998
@@ -1061,31 +1061,6 @@
 		goto out;
 
 	/*
-	 * Security: Check that the export is valid for dentry <gam3@acm.org>
-	 */
-	if (fh->fh_dev != fh->fh_xdev) {
-		printk("fh_verify: Security: export on other device"
-		       " (%d, %d).\n", fh->fh_dev, fh->fh_xdev);
-		goto out;
-	} else {
-		struct dentry *tdentry = dentry;
-
-		do {
-			if (exp->ex_dentry == tdentry) {
-				error = 0;
-				break;
-			}
-			if (tdentry->d_parent == tdentry)
-				break;
-		} while ((tdentry = tdentry->d_parent));
-		if (error) {
-			printk("fh_verify: Security: %s/%s bad export.\n",
-			       dentry->d_parent->d_name.name,
-			       dentry->d_name.name);
-			goto out;
-		}
-	}
-	/*
 	 * Note:  it's possible the returned dentry won't be the one in the
 	 * file handle.  We can correct the file handle for our use, but
 	 * unfortunately the client will keep sending the broken one.  Let's
@@ -1105,6 +1080,7 @@
 check_type:
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
+	exp = fhp->fh_export;
 	if (type > 0 && (inode->i_mode & S_IFMT) != type) {
 		error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
 		goto out;
@@ -1114,9 +1090,45 @@
 		goto out;
 	}
 
+	/*
+	 * Security: Check that the export is valid for dentry <gam3@acm.org>
+	 */
+	if (fh->fh_dev != fh->fh_xdev) {
+		printk("fh_verify: Security: export on other device"
+		       " (%d, %d).\n", fh->fh_dev, fh->fh_xdev);
+		goto out;
+	} else if (exp->ex_dentry != dentry) {
+		struct dentry *tdentry = dentry;
+		int err2 = 0;
+
+		error = nfserr_stale;
+		do {
+			tdentry = tdentry->d_parent;
+			if (exp->ex_dentry == tdentry) {
+				error = 0;
+				break;
+			}
+			if ((err2 = nfsd_permission(exp, tdentry, MAY_EXEC))) {
+				error = err2;
+#ifdef NFSD_PARANOIA
+				goto out1;
+#else
+				goto out;
+#endif
+			}
+		} while ((tdentry != tdentry->d_parent));
+		if (error) {
+			printk("fh_verify: Security: %s/%s bad export.\n",
+			       dentry->d_parent->d_name.name,
+			       dentry->d_name.name);
+			goto out;
+		}
+	}
+
 	/* Finally, check access permissions. */
-	error = nfsd_permission(fhp->fh_export, dentry, access);
+	error = nfsd_permission(exp, dentry, access);
 #ifdef NFSD_PARANOIA
+out1:
 if (error)
 printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, access, error);
