⬢ DragonFlyBSD Kernel Audit
DF-2997 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/nfs/nfs_vnops.c
+++ b/sys/vfs/nfs/nfs_vnops.c
@@ -1269,7 +1269,15 @@
 nfsmout:
 	if (error) {
 		if (newvp != NULLVP) {
-			vrele(newvp);
+			/*
+			 * nfs_nget() returned newvp LK_EXCLUSIVE-locked;
+			 * only the dvp-echo case (vref'd, lock owned by the
+			 * caller) must be released without unlocking.
+			 */
+			if (newvp == dvp)
+				vrele(newvp);
+			else
+				vput(newvp);
 			*vpp = NULLVP;
 		}
 		if ((cnp->cn_nameiop == NAMEI_CREATE || 
@@ -2345,7 +2353,8 @@
 	 */
 	if (error == EEXIST || (!error && !gotvp)) {
 		if (newvp) {
-			vrele(newvp);
+			/* nfsm_mtofh()-sourced: still LK_EXCLUSIVE-locked */
+			vput(newvp);
 			newvp = NULL;
 		}
 		error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
@@ -2357,8 +2366,17 @@
 		}
 	}
 	if (error) {
-		if (newvp)
-			vrele(newvp);
+		if (newvp) {
+			/*
+			 * newvp came from nfs_nget()/nfs_lookitup() and is
+			 * LK_EXCLUSIVE-locked; only the lookitup dvp-echo
+			 * case must be released without unlocking.
+			 */
+			if (newvp == dvp)
+				vrele(newvp);
+			else
+				vput(newvp);
+		}
 	} else {
 		nfs_knote(dvp, NOTE_WRITE | NOTE_LINK);
 		*ap->a_vpp = newvp;