Set a watch on the super block's root inode including the mask bit FAN_EVENT_ON_SB to get notified on the events of all the inodes on the same super block. When requesting to add a super block root watch, any file on the file system can be passed as input argument for fanotify_mark(). The mark will be added to the root inode of the file system that file belongs to. The super block watch cannot be set with FAN_MARK_MOUNT flag, because a super block watch is an inode mark, not a mount mark. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/notify/fanotify/fanotify.c | 1 + fs/notify/fanotify/fanotify_user.c | 15 ++++++++++++--- include/uapi/linux/fanotify.h | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index a647e7b..67feeb6 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -237,6 +237,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF); BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF); BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD); + BUILD_BUG_ON(FAN_EVENT_ON_SB != FS_EVENT_ON_SB); BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW); BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM); BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 13015ee..e57c82a 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -902,9 +902,9 @@ SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags, } #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS - if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD)) + if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_DESCENDANT)) #else - if (mask & ~(FAN_ALL_EVENTS | FAN_EVENT_ON_CHILD)) + if (mask & ~(FAN_ALL_EVENTS | FAN_EVENT_ON_DESCENDANT)) #endif return -EINVAL; @@ -927,6 +927,12 @@ SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags, group->priority == FS_PRIO_0) goto fput_and_out; + /* Super block root watch is not a mount watch */ + ret = -EINVAL; + if ((mask & FAN_EVENT_ON_SB) && + (flags & FAN_MARK_MOUNT)) + goto fput_and_out; + if (flags & FAN_MARK_FLUSH) { ret = 0; if (flags & FAN_MARK_MOUNT) @@ -941,7 +947,9 @@ SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags, goto fput_and_out; /* inode held in place by reference to path; group by fget on fd */ - if (!(flags & FAN_MARK_MOUNT)) + if (mask & FAN_EVENT_ON_SB) + inode = path.dentry->d_sb->s_root->d_inode; + else if (!(flags & FAN_MARK_MOUNT)) inode = path.dentry->d_inode; /* @@ -950,6 +958,7 @@ SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags, * even if the events happened on another mount point. */ if ((flags & FAN_MARK_MOUNT) || + (mask & FAN_EVENT_ON_SB) || group->fanotify_data.flags & FAN_EVENT_INFO_PARENT) mnt = path.mnt; diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h index 95b8335..b202e09 100644 --- a/include/uapi/linux/fanotify.h +++ b/include/uapi/linux/fanotify.h @@ -25,8 +25,11 @@ #define FAN_ONDIR 0x40000000 /* event occurred against dir */ +#define FAN_EVENT_ON_SB 0x01000000 /* interested in all sb inodes */ #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ +#define FAN_EVENT_ON_DESCENDANT (FAN_EVENT_ON_CHILD | FAN_EVENT_ON_SB) + /* helper events */ #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ #define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO) /* moves */ -- 2.7.4