aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2025-07-18 14:25:28 +0000
committerMark Johnston <markj@FreeBSD.org>2026-08-05 15:15:16 +0000
commit9f2c32c1924b524f9e353bee74884d263b273a4f (patch)
tree9a714099d5f8e7aa97a3dc24df9e02a57da9d883
parente8c54222acdbb977c4164667627b6ee569d2eb90 (diff)
inotify: Fix a couple of locking bugs
When hooking vop_rename_post(), the preexisting dst vnode will be unlocked. But, we need to invoke VOP_GETATTR on it in vn_inotify() to check its link count. In inotify_unlink_watch_locked(), the vnode interlock is not held, so don't use vn_irflag_unset_locked(). Reviewed by: kib Fixes: f1f230439fa4 ("vfs: Initial revision of inotify") Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D51401 (cherry picked from commit af0ec3fa29cad823d0196538381f1e832f5974a7)
-rw-r--r--sys/kern/vfs_inotify.c5
-rw-r--r--sys/sys/inotify.h14
2 files changed, 14 insertions, 5 deletions
diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c
index 46971c78440c..035c2c9eb290 100644
--- a/sys/kern/vfs_inotify.c
+++ b/sys/kern/vfs_inotify.c
@@ -368,7 +368,7 @@ inotify_unlink_watch_locked(struct inotify_softc *sc, struct inotify_watch *watc
TAILQ_REMOVE(&vp->v_pollinfo->vpi_inotify, watch, vlink);
if (TAILQ_EMPTY(&vp->v_pollinfo->vpi_inotify))
- vn_irflag_unset_locked(vp, VIRF_INOTIFY);
+ vn_irflag_unset(vp, VIRF_INOTIFY);
}
/*
@@ -672,7 +672,8 @@ vn_inotify(struct vnode *vp, struct vnode *dvp, struct componentname *cnp,
struct vattr va;
int error;
- error = VOP_GETATTR(vp, &va, cnp->cn_cred);
+ error = VOP_GETATTR(vp, &va,
+ cnp->cn_cred);
if (error == 0 && va.va_nlink != 0)
selfevent = 0;
}
diff --git a/sys/sys/inotify.h b/sys/sys/inotify.h
index 65dc5dba43f3..d1f23d5898bb 100644
--- a/sys/sys/inotify.h
+++ b/sys/sys/inotify.h
@@ -107,11 +107,18 @@ void vn_inotify_revoke(struct vnode *);
} while (0)
/* Log an inotify event using a specific name for the vnode. */
-#define INOTIFY_NAME(vp, dvp, cnp, ev) do { \
+#define INOTIFY_NAME_LOCK(vp, dvp, cnp, ev, lock) do { \
if (__predict_false((vn_irflag_read(vp) & VIRF_INOTIFY) != 0 || \
- (vn_irflag_read(dvp) & VIRF_INOTIFY) != 0)) \
+ (vn_irflag_read(dvp) & VIRF_INOTIFY) != 0)) { \
+ if (lock) \
+ vn_lock((vp), LK_SHARED | LK_RETRY); \
VOP_INOTIFY((vp), (dvp), (cnp), (ev), 0); \
+ if (lock) \
+ VOP_UNLOCK(vp); \
+ } \
} while (0)
+#define INOTIFY_NAME(vp, dvp, cnp, ev) \
+ INOTIFY_NAME_LOCK((vp), (dvp), (cnp), (ev), false)
extern __uint32_t inotify_rename_cookie;
@@ -126,7 +133,8 @@ extern __uint32_t inotify_rename_cookie;
VOP_INOTIFY((vp), (tdvp), (tcnp), IN_MOVED_TO, cookie); \
} \
if ((tvp) != NULL) \
- INOTIFY_NAME((tvp), (tdvp), (tcnp), _IN_MOVE_DELETE); \
+ INOTIFY_NAME_LOCK((tvp), (tdvp), (tcnp), \
+ _IN_MOVE_DELETE, true); \
} while (0)
#define INOTIFY_REVOKE(vp) do { \