@@ -107,6 +107,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
int data_type, __kernel_fsid_t *fsid)
{
__u32 marks_mask = 0, marks_ignored_mask = 0;
+ __u32 test_mask, user_mask = FANOTIFY_EVENT_TYPES;
const struct path *path = data;
struct fsnotify_mark *mark;
int type, err;
@@ -144,12 +145,38 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
marks_ignored_mask |= mark->ignored_mask;
}
+ test_mask = event_mask & marks_mask & ~marks_ignored_mask;
+
+ /*
+ * dirent modification events (create/delete/move) do not carry the
+ * child entry name/inode information. Instead, we report FAN_ONDIR
+ * for mkdir/rmdir so user can differentiate them from creat/unlink.
+ *
+ * For backward compatibility and consistency, do not report FAN_ONDIR
+ * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR
+ * to user in FAN_REPORT_FID mode for all event types.
+ */
+ if (fsid) {
+ /* Do not report FAN_ONDIR without an event type */
+ BUILD_BUG_ON(FANOTIFY_EVENT_TYPES & FANOTIFY_EVENT_FLAGS);
+ if (!(test_mask & FANOTIFY_EVENT_TYPES))
+ return 0;
+
+ user_mask |= FAN_ONDIR;
+ }
+
+ /*
+ * Unlike legacy fanotify events (open/access/close), dirent events
+ * for subdir entries (mkdir/rmdir) will be reported regardless if
+ * user requested FAN_ONDIR, but the FAN_ONDIR flag itself will only
+ * be reported if the user asked for it.
+ */
if (event_mask & FS_ISDIR &&
+ !(event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) &&
!(marks_mask & FS_ISDIR & ~marks_ignored_mask))
return 0;
- return event_mask & FANOTIFY_OUTGOING_EVENTS & marks_mask &
- ~marks_ignored_mask;
+ return test_mask & user_mask;
}
static struct fanotify_event_fid *fanotify_alloc_fid(struct inode *inode,
@@ -61,13 +61,16 @@
#define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM | \
FAN_OPEN_EXEC_PERM)
+/* Events types that may be reported from vfs */
+#define FANOTIFY_EVENT_TYPES (FANOTIFY_EVENTS | \
+ FANOTIFY_PERM_EVENTS)
+
/* Extra flags that may be reported with event or control handling of events */
#define FANOTIFY_EVENT_FLAGS (FAN_EVENT_ON_CHILD | FAN_ONDIR)
/* Events that may be reported to user */
-#define FANOTIFY_OUTGOING_EVENTS (FANOTIFY_EVENTS | \
- FANOTIFY_PERM_EVENTS | \
- FAN_Q_OVERFLOW)
+#define FANOTIFY_OUTGOING_EVENTS (FANOTIFY_EVENT_TYPES | \
+ FAN_Q_OVERFLOW | FAN_ONDIR)
#define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \
FANOTIFY_EVENT_FLAGS)
dirent modification events (create/delete/move) do not carry the child entry name/inode information. Instead, we report FAN_ONDIR for mkdir/rmdir so user can differentiate them from creat/unlink. For backward compatibility and consistency, do not report FAN_ONDIR to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR to user in FAN_REPORT_FID mode for all event types. Unlike legacy fanotify events (open/access/close), dirent events for subdir entries (mkdir/rmdir) will be reported regardless if user requested FAN_ONDIR, but the FAN_ONDIR flag itself will only be reported if the user asked for it. Cc: <linux-api@vger.kernel.org> Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/notify/fanotify/fanotify.c | 31 +++++++++++++++++++++++++++++-- include/linux/fanotify.h | 9 ++++++--- 2 files changed, 35 insertions(+), 5 deletions(-)