diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index db80a0d89d24..81267260d1b9 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -485,7 +485,8 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags, __u64 mask, int dfd, const char __user * pathname) { - struct inode *inode; + struct inode *inode = NULL; + struct vfsmount *mnt = NULL; struct fsnotify_group *group; struct file *filp; struct path path; @@ -515,16 +516,22 @@ SYSCALL_DEFINE(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 */ - inode = path.dentry->d_inode; + if (!(flags & FAN_MARK_ON_VFSMOUNT)) + inode = path.dentry->d_inode; + else + mnt = path.mnt; group = filp->private_data; /* create/update an inode mark */ switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) { case FAN_MARK_ADD: - ret = fanotify_add_inode_mark(group, inode, mask); + if (flags & FAN_MARK_ON_VFSMOUNT) + ret = fanotify_add_vfsmount_mark(group, mnt, mask); + else + ret = fanotify_add_inode_mark(group, inode, mask); break; case FAN_MARK_REMOVE: - ret = fanotify_remove_mark(group, inode, NULL, mask); + ret = fanotify_remove_mark(group, inode, mnt, mask); break; default: ret = -EINVAL; diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 5f633af4d1b0..e25d348188ca 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -29,11 +29,13 @@ #define FAN_MARK_REMOVE 0x00000002 #define FAN_MARK_DONT_FOLLOW 0x00000004 #define FAN_MARK_ONLYDIR 0x00000008 +#define FAN_MARK_ON_VFSMOUNT 0x00000010 #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ FAN_MARK_REMOVE |\ FAN_MARK_DONT_FOLLOW |\ - FAN_MARK_ONLYDIR) + FAN_MARK_ONLYDIR |\ + FAN_MARK_ON_VFSMOUNT) /* * All of the events - we build the list by hand so that we can add flags in