[PATCH v2 9/9] fanotify: report FAN_ONDIR to listener for filename events

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For events reporting fid of parent (create/delete/move), we report
FAN_ONDIR, so user can differentiate mkdir/rmdir from creat/unlink events.
Unlike legacy fanotify events (open/access/close), 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.

For backward compatibility, we do not report FAN_ONDIR to user for legacy
fanotify events.  While it is not documented that this event flags is NOT
reported, it is better to be on the safe side and preserve the existing
behavior.

At the moment the new event FAN_ATTRIB (setattr/setxattr) behaves like
the legacy events, because like them, it reports the fid of the victim,
so user has a way to identify the victim as a directory. Not sure if
FAN_ATTRIB should behave like filename events w.r.t FAN_ONDIR and not
sure whether legacy events behavior should change with FAN_REPORT_FID.

Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
---
 fs/notify/fanotify/fanotify.c | 42 ++++++++++++++++++++++++++++++-----
 include/linux/fanotify.h      |  9 +++++---
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index a2d63e86ba47..f1a431b1a4d9 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -119,10 +119,12 @@ static struct dentry *fanotify_event_dentry(const void *data, int data_type)
  * requested by the user, will not be present in the returned mask.
  */
 static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
-				       u32 event_mask, const void *data,
-				       int data_type)
+				     u32 event_mask, const void *data,
+				     int data_type)
 {
 	__u32 marks_mask = 0, marks_ignored_mask = 0;
+	__u32 test_mask, user_mask = FANOTIFY_EVENT_TYPES;
+	bool is_filename = (event_mask & FANOTIFY_FILENAME_EVENTS);
 	struct dentry *dentry = fanotify_event_dentry(data, data_type);
 	struct fsnotify_mark *mark;
 	int type;
@@ -151,12 +153,42 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 		marks_ignored_mask |= mark->ignored_mask;
 	}
 
-	if (d_is_dir(dentry) &&
+	if (is_filename) {
+		/*
+		 * For filename events (create/delete/move), we report
+		 * FAN_ONDIR for mkdir/rmdir so user can differentiate them
+		 * from creat/unlink events. Unlike legacy fanotify events
+		 * (open/access/close), 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.
+		 */
+		user_mask |= FAN_ONDIR;
+	} else {
+		/*
+		 * For backward compatibility, do not report FAN_ONDIR to user
+		 * in legacy fanotify mode (reporting fd). While it is not
+		 * documented that this event flag is NOT reported, it is
+		 * better to be on the safe side and preserve the existing
+		 * behavior.
+		 */
+		BUILD_BUG_ON(FANOTIFY_EVENT_TYPES & FANOTIFY_EVENT_FLAGS);
+	}
+
+	/* Do not report FAN_ONDIR without an event type */
+	test_mask = event_mask & marks_mask & ~marks_ignored_mask;
+	if (!(test_mask & FANOTIFY_EVENT_TYPES))
+		return 0;
+
+	/*
+	 * Unlike legacy fanotify events (open/access/close), mkdir/rmdir
+	 * events will be reported even if FAN_ONDIR is in ignore mask, but
+	 * the FAN_ONDIR flag itself will not be reported in this case.
+	 */
+	if (d_is_dir(dentry) && !is_filename &&
 	    !(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 dentry *dentry,
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index fbda82b25ae3..7ccbcebc35e7 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -59,13 +59,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)
-- 
2.17.1




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux