Thread (14 messages) 14 messages, 7 authors, 2025-01-28
STALE497d

[PATCH v4 4/4] vfs: add notifications for mount attribute change

From: Miklos Szeredi <hidden>
Date: 2025-01-23 19:41:20
Also in: linux-fsdevel
Subsystem: fanotify, filesystems (vfs and infrastructure), fsnotify: filesystem notification infrastructure, the rest · Maintainers: Jan Kara, Alexander Viro, Christian Brauner, Linus Torvalds

Notify when mount flags, propagation or idmap changes.

Just like attach and detach, no details are given in the notification, only
the mount ID.

Signed-off-by: Miklos Szeredi <redacted>
---
 fs/namespace.c                   | 27 +++++++++++++++++++++++++++
 fs/notify/fanotify/fanotify.c    |  2 +-
 fs/notify/fanotify/fanotify.h    |  2 +-
 fs/notify/fsnotify.c             |  2 +-
 include/linux/fanotify.h         |  2 +-
 include/linux/fsnotify.h         |  5 +++++
 include/linux/fsnotify_backend.h |  5 ++++-
 include/uapi/linux/fanotify.h    |  1 +
 8 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/fs/namespace.c b/fs/namespace.c
index 948348a37f6c..9b9b13665dce 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2807,6 +2807,9 @@ static int do_change_type(struct path *path, int ms_flags)
 		change_mnt_propagation(m, type);
 	unlock_mount_hash();
 
+	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
+		fsnotify_mnt_change(m->mnt_ns, &m->mnt);
+
  out_unlock:
 	namespace_unlock();
 	return err;
@@ -3089,6 +3092,12 @@ static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags)
 	unlock_mount_hash();
 	up_read(&sb->s_umount);
 
+	if (!ret) {
+		down_read(&namespace_sem);
+		fsnotify_mnt_change(mnt->mnt_ns, &mnt->mnt);
+		up_read(&namespace_sem);
+	}
+
 	mnt_warn_timestamp_expiry(path, &mnt->mnt);
 
 	return ret;
@@ -3141,6 +3150,13 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
 		up_write(&sb->s_umount);
 	}
 
+	if (!err) {
+		down_read(&namespace_sem);
+		fsnotify_mnt_change(mnt->mnt_ns, &mnt->mnt);
+		up_read(&namespace_sem);
+	}
+
+
 	mnt_warn_timestamp_expiry(path, &mnt->mnt);
 
 	put_fs_context(fc);
@@ -4708,6 +4724,8 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
 				return err;
 			}
 		}
+	} else {
+		down_read(&namespace_sem);
 	}
 
 	err = -EINVAL;
@@ -4743,10 +4761,19 @@ static int do_mount_setattr(struct path *path, struct mount_kattr *kattr)
 out:
 	unlock_mount_hash();
 
+	if (!err) {
+		struct mount *m;
+
+		for (m = mnt; m; m = kattr->recurse ? next_mnt(m, mnt) : NULL)
+			fsnotify_mnt_change(m->mnt_ns, &m->mnt);
+	}
+
 	if (kattr->propagation) {
 		if (err)
 			cleanup_group_ids(mnt, NULL);
 		namespace_unlock();
+	} else {
+		up_read(&namespace_sem);
 	}
 
 	return err;
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index b1937f92f105..c7ddd145f3d8 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -934,7 +934,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
 	BUILD_BUG_ON(FAN_FS_ERROR != FS_ERROR);
 	BUILD_BUG_ON(FAN_RENAME != FS_RENAME);
 
-	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 23);
+	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 24);
 
 	mask = fanotify_group_event_mask(group, iter_info, &match_mask,
 					 mask, data, data_type, dir);
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index f1a7cbedc9e3..8d6289da06f1 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -471,7 +471,7 @@ static inline bool fanotify_is_error_event(u32 mask)
 
 static inline bool fanotify_is_mnt_event(u32 mask)
 {
-	return mask & (FAN_MNT_ATTACH | FAN_MNT_DETACH);
+	return mask & FANOTIFY_MOUNT_EVENTS;
 }
 
 static inline const struct path *fanotify_event_path(struct fanotify_event *event)
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 2b2c3fd907c7..5872dd27172d 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -660,7 +660,7 @@ static __init int fsnotify_init(void)
 {
 	int ret;
 
-	BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25);
+	BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26);
 
 	ret = init_srcu_struct(&fsnotify_mark_srcu);
 	if (ret)
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index fc142be2542d..61e112d25303 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -100,7 +100,7 @@
 /* Events that can only be reported with data type FSNOTIFY_EVENT_ERROR */
 #define FANOTIFY_ERROR_EVENTS	(FAN_FS_ERROR)
 
-#define FANOTIFY_MOUNT_EVENTS	(FAN_MNT_ATTACH | FAN_MNT_DETACH)
+#define FANOTIFY_MOUNT_EVENTS	(FAN_MNT_ATTACH | FAN_MNT_DETACH | FAN_MNT_CHANGE)
 
 /* Events that user can request to be notified on */
 #define FANOTIFY_EVENTS		(FANOTIFY_PATH_EVENTS | \
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index ea998551dd0d..ba3e05c69aaa 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -483,4 +483,9 @@ static inline void fsnotify_mnt_move(struct mnt_namespace *ns, struct vfsmount *
 	fsnotify_mnt(FS_MNT_MOVE, ns, mnt);
 }
 
+static inline void fsnotify_mnt_change(struct mnt_namespace *ns, struct vfsmount *mnt)
+{
+	fsnotify_mnt(FS_MNT_CHANGE, ns, mnt);
+}
+
 #endif	/* _LINUX_FS_NOTIFY_H */
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 6c3e3a4a7b10..54e01803e309 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -58,6 +58,8 @@
 
 #define FS_MNT_ATTACH		0x01000000	/* Mount was attached */
 #define FS_MNT_DETACH		0x02000000	/* Mount was detached */
+#define FS_MNT_CHANGE		0x04000000	/* Mount was changed */
+
 #define FS_MNT_MOVE		(FS_MNT_ATTACH | FS_MNT_DETACH)
 
 /*
@@ -106,7 +108,8 @@
 			     FS_EVENTS_POSS_ON_CHILD | \
 			     FS_DELETE_SELF | FS_MOVE_SELF | \
 			     FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
-			     FS_ERROR | FS_MNT_ATTACH | FS_MNT_DETACH)
+			     FS_ERROR | \
+			     FS_MNT_ATTACH | FS_MNT_DETACH | FS_MNT_CHANGE )
 
 /* Extra flags that may be reported with event or control handling of events */
 #define ALL_FSNOTIFY_FLAGS  (FS_ISDIR | FS_EVENT_ON_CHILD | FS_DN_MULTISHOT)
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 69340e483ae7..256fc5755b45 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -27,6 +27,7 @@
 #define FAN_OPEN_EXEC_PERM	0x00040000	/* File open/exec in perm check */
 #define FAN_MNT_ATTACH		0x01000000	/* Mount was attached */
 #define FAN_MNT_DETACH		0x02000000	/* Mount was detached */
+#define FAN_MNT_CHANGE		0x04000000	/* Mount was changed */
 
 #define FAN_EVENT_ON_CHILD	0x08000000	/* Interested in child events */
 
-- 
2.47.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help