[PATCH v4 4/4] vfs: add notifications for mount attribute change
Christian Brauner
brauner at kernel.org
Fri Jan 24 15:38:25 UTC 2025
On Thu, Jan 23, 2025 at 08:41:07PM +0100, Miklos Szeredi wrote:
> 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 <mszeredi at redhat.com>
> ---
I think this is a good next step but I would first go with the minimal
functionality of notifying about mount topology changes for v6.15.
Btw, if we notify in do_remount() on the mount that triggered
superblock reconfiguration then we also need to trigger in
vfs_cmd_reconfigure() aka fsconfig(FSCONFIG_CMD_RECONFIGURE) but the
mount that was used to change superblock options is only available in
fspick() currently. That would need to be handled.
But I think this patch makes more sense in follow-up releases.
> 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
>
More information about the Linux-security-module-archive
mailing list