summaryrefslogtreecommitdiff
blob: fe9e97efd2987cbedda757c732e1fe3116713979 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Index: sys/fs/nfsserver/nfs_nfsdserv.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdserv.c	(revision 264251)
+++ sys/fs/nfsserver/nfs_nfsdserv.c	(working copy)
@@ -1457,10 +1457,23 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgr
 		nfsvno_relpathbuf(&fromnd);
 		goto out;
 	}
+	/*
+	 * Unlock dp in this code section, so it is unlocked before
+	 * tdp gets locked. This avoids a potential LOR if tdp is the
+	 * parent directory of dp.
+	 */
 	if (nd->nd_flag & ND_NFSV4) {
 		tdp = todp;
 		tnes = *toexp;
-		tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 0);
+		if (dp != tdp) {
+			NFSVOPUNLOCK(dp, 0);
+			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
+			    p, 0);	/* Might lock tdp. */
+		} else {
+			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
+			    p, 1);
+			NFSVOPUNLOCK(dp, 0);
+		}
 	} else {
 		tfh.nfsrvfh_len = 0;
 		error = nfsrv_mtofh(nd, &tfh);
@@ -1481,10 +1494,12 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgr
 			tnes = *exp;
 			tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
 			    p, 1);
+			NFSVOPUNLOCK(dp, 0);
 		} else {
+			NFSVOPUNLOCK(dp, 0);
 			nd->nd_cred->cr_uid = nd->nd_saveduid;
 			nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
-			    0, p);
+			    0, p);	/* Locks tdp. */
 			if (tdp) {
 				tdirfor_ret = nfsvno_getattr(tdp, &tdirfor,
 				    nd->nd_cred, p, 1);
@@ -1499,7 +1514,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgr
 		if (error) {
 			if (tdp)
 				vrele(tdp);
-			vput(dp);
+			vrele(dp);
 			nfsvno_relpathbuf(&fromnd);
 			nfsvno_relpathbuf(&tond);
 			goto out;
@@ -1514,7 +1529,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgr
 		}
 		if (tdp)
 			vrele(tdp);
-		vput(dp);
+		vrele(dp);
 		nfsvno_relpathbuf(&fromnd);
 		nfsvno_relpathbuf(&tond);
 		goto out;
@@ -1523,7 +1538,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgr
 	/*
 	 * Done parsing, now down to business.
 	 */
-	nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 1, exp, p, &fdirp);
+	nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, p, &fdirp);
 	if (nd->nd_repstat) {
 		if (nd->nd_flag & ND_NFSV3) {
 			nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,