patch-2.1.127 linux/fs/nfsd/nfsfh.c

Next file: linux/fs/nfsd/nfssvc.c
Previous file: linux/fs/nfsd/export.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.126/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
@@ -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_READ))) {
+				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);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov