git: af0ec3fa29ca - main - inotify: Fix a couple of locking bugs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Jul 2025 14:30:44 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=af0ec3fa29cad823d0196538381f1e832f5974a7
commit af0ec3fa29cad823d0196538381f1e832f5974a7
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-07-18 14:25:28 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-07-18 14:25:28 +0000
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
---
sys/kern/vfs_inotify.c | 5 +++--
sys/sys/inotify.h | 14 +++++++++++---
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c
index 2b42228465a4..d3cd0d1f9832 100644
--- a/sys/kern/vfs_inotify.c
+++ b/sys/kern/vfs_inotify.c
@@ -371,7 +371,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);
}
/*
@@ -675,7 +675,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 { \