DragonFlyBSD Kernel Audit
DF-2994 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/nfs/nfs_serv.c
+++ b/sys/vfs/nfs/nfs_serv.c
@@ -571,12 +571,20 @@ nfsrv_lookup(struct nfsrv_descript *nfsd
 			if (error == 0) {
 				/*
 				 * Found an index file. Get rid of
 				 * the old references.  transfer vp and
 				 * load up the new vp.  Fortunately we do
 				 * not have to deal with dvp, that would
 				 * be a huge mess.
 				 */
 				if (dirp)	
 					vrele(dirp);
 				dirp = vp;
 				vp = NULL;
 				error = cache_vget(&nd.nl_nch, nd.nl_cred,
 							LK_EXCLUSIVE, &vp);
 				KKASSERT(error == 0);
+			} else {
+				/*
+				 * DF-2994: the index lookup failed, so we
+				 * continue with the original vp — which was
+				 * unlocked above.  Restore its lock so the
+				 * vput() paths below cannot release an
+				 * unheld lock (guaranteed panic).
+				 */
+				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 			}
 			error = 0;
 		}