Blob Blame History Raw
From 2f02fd3fa13e51713b630164f8a8e5b42de8283b Mon Sep 17 00:00:00 2001
From: Amir Goldstein <amir73il@gmail.com>
Date: Sun, 24 May 2020 10:24:41 +0300
Subject: [PATCH] fanotify: fix ignore mask logic for events on child and on
 dir
Git-commit: 2f02fd3fa13e51713b630164f8a8e5b42de8283b
Patch-mainline: v5.7-rc1
References: bsc#1172719

The comments in fanotify_group_event_mask() say:

  "If the event is on dir/child and this mark doesn't care about
   events on dir/child, don't send it!"

Specifically, mount and filesystem marks do not care about events
on child, but they can still specify an ignore mask for those events.
For example, a group that has:
- A mount mark with mask 0 and ignore_mask FAN_OPEN
- An inode mark on a directory with mask FAN_OPEN | FAN_OPEN_EXEC
  with flag FAN_EVENT_ON_CHILD

A child file open for exec would be reported to group with the FAN_OPEN
event despite the fact that FAN_OPEN is in ignore mask of mount mark,
because the mark iteration loop skips over non-inode marks for events
on child when calculating the ignore mask.

Move ignore mask calculation to the top of the iteration loop block
before excluding marks for events on dir/child.

Link: https://lore.kernel.org/r/20200524072441.18258-1-amir73il@gmail.com
Reported-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/linux-fsdevel/20200521162443.GA26052@quack2.suse.cz/
Fixes: 55bf882c7f13 "fanotify: fix merging marks masks with FAN_ONDIR"
Fixes: b469e7e47c8a "fanotify: fix handling of events on child..."
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
 fs/notify/fanotify/fanotify.c |   19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -111,11 +111,12 @@ static bool fanotify_should_send_event(s
 	 * If the event is on dir and this mark doesn't care about
 	 * events on dir, don't send it!
 	 */
-	if (inode_mark &&
-	    (!(event_mask & FS_EVENT_ON_CHILD) ||
-	     (inode_mark->mask & FS_EVENT_ON_CHILD)) &&
-	    (!(event_mask & FS_ISDIR) || inode_mark->mask & FS_ISDIR)) {
-		marks_mask |= inode_mark->mask;
+	if (inode_mark) {
+		if ((!(event_mask & FS_EVENT_ON_CHILD) ||
+		     (inode_mark->mask & FS_EVENT_ON_CHILD)) &&
+		    (!(event_mask & FS_ISDIR) || inode_mark->mask & FS_ISDIR))
+			marks_mask |= inode_mark->mask;
+		/* Apply ignore mask regardless of ISDIR and ON_CHILD flags */
 		marks_ignored_mask |= inode_mark->ignored_mask;
 	}
 
@@ -125,9 +126,11 @@ static bool fanotify_should_send_event(s
 	 * If the event is on dir and this mark doesn't care about
 	 * events on dir, don't send it!
 	 */
-	if (vfsmnt_mark && !(event_mask & FS_EVENT_ON_CHILD) &&
-	    (!(event_mask & FS_ISDIR) || vfsmnt_mark->mask & FS_ISDIR)) {
-		marks_mask |= vfsmnt_mark->mask;
+	if (vfsmnt_mark) {
+		if (!(event_mask & FS_EVENT_ON_CHILD) &&
+		    (!(event_mask & FS_ISDIR) || vfsmnt_mark->mask & FS_ISDIR))
+			marks_mask |= vfsmnt_mark->mask;
+		/* Apply ignore mask regardless of ISDIR and ON_CHILD flags */
 		marks_ignored_mask |= vfsmnt_mark->ignored_mask;
 	}