DragonFlyBSD Kernel Audit
DF-3056 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/dirfs/dirfs_vnops.c b/sys/vfs/dirfs/dirfs_vnops.c
index a9acfbb5..3ce2d52e 100644
--- a/sys/vfs/dirfs/dirfs_vnops.c
+++ b/sys/vfs/dirfs/dirfs_vnops.c
@@ -984,6 +984,21 @@ dirfs_nrename(struct vop_nrename_args *ap)
 	if (error == 0) {
 		vp = fncp->nc_vp;	/* file being renamed */
 		dnp = VP_TO_NODE(vp);
+		/*
+		 * If the file moved to a different directory the parent
+		 * pointer must follow: dirfs_findfd() and
+		 * dirfs_node_absolute_path() build every host path by
+		 * walking dn_parent, and a stale parent makes later
+		 * setattr/getattr/unlink operations act on whatever file
+		 * occupies the OLD path.
+		 */
+		if (dnp->dn_parent != tdnp) {
+			dirfs_node_t opnp = dnp->dn_parent;
+			dnp->dn_parent = tdnp;
+			dirfs_node_ref(tdnp);
+			if (opnp)
+				dirfs_node_drop(dmp, opnp);
+		}
 		dirfs_node_setname(dnp, tncp->nc_name, tncp->nc_nlen);
 		dirfs_knote(fdvp, NOTE_RENAME);
 		/*