| From foo@baz Sun Jun 17 12:07:33 CEST 2018 |
| From: Amir Goldstein <amir73il@gmail.com> |
| Date: Thu, 5 Apr 2018 16:18:03 +0300 |
| Subject: fsnotify: fix ignore mask logic in send_to_group() |
| |
| From: Amir Goldstein <amir73il@gmail.com> |
| |
| [ Upstream commit 92183a42898dc400b89da35685d1814ac6acd3d8 ] |
| |
| The ignore mask logic in send_to_group() does not match the logic |
| in fanotify_should_send_event(). In the latter, a vfsmount mark ignore |
| mask precedes an inode mark mask and in the former, it does not. |
| |
| That difference may cause events to be sent to fanotify backend for no |
| reason. Fix the logic in send_to_group() to match that of |
| fanotify_should_send_event(). |
| |
| Signed-off-by: Amir Goldstein <amir73il@gmail.com> |
| Signed-off-by: Jan Kara <jack@suse.cz> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/notify/fsnotify.c | 25 +++++++++++-------------- |
| 1 file changed, 11 insertions(+), 14 deletions(-) |
| |
| --- a/fs/notify/fsnotify.c |
| +++ b/fs/notify/fsnotify.c |
| @@ -192,8 +192,9 @@ static int send_to_group(struct inode *t |
| struct fsnotify_iter_info *iter_info) |
| { |
| struct fsnotify_group *group = NULL; |
| - __u32 inode_test_mask = 0; |
| - __u32 vfsmount_test_mask = 0; |
| + __u32 test_mask = (mask & ~FS_EVENT_ON_CHILD); |
| + __u32 marks_mask = 0; |
| + __u32 marks_ignored_mask = 0; |
| |
| if (unlikely(!inode_mark && !vfsmount_mark)) { |
| BUG(); |
| @@ -213,29 +214,25 @@ static int send_to_group(struct inode *t |
| /* does the inode mark tell us to do something? */ |
| if (inode_mark) { |
| group = inode_mark->group; |
| - inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); |
| - inode_test_mask &= inode_mark->mask; |
| - inode_test_mask &= ~inode_mark->ignored_mask; |
| + marks_mask |= inode_mark->mask; |
| + marks_ignored_mask |= inode_mark->ignored_mask; |
| } |
| |
| /* does the vfsmount_mark tell us to do something? */ |
| if (vfsmount_mark) { |
| - vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); |
| group = vfsmount_mark->group; |
| - vfsmount_test_mask &= vfsmount_mark->mask; |
| - vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; |
| - if (inode_mark) |
| - vfsmount_test_mask &= ~inode_mark->ignored_mask; |
| + marks_mask |= vfsmount_mark->mask; |
| + marks_ignored_mask |= vfsmount_mark->ignored_mask; |
| } |
| |
| pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" |
| - " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" |
| + " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x" |
| " data=%p data_is=%d cookie=%d\n", |
| - __func__, group, to_tell, mask, inode_mark, |
| - inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, |
| + __func__, group, to_tell, mask, inode_mark, vfsmount_mark, |
| + marks_mask, marks_ignored_mask, data, |
| data_is, cookie); |
| |
| - if (!inode_test_mask && !vfsmount_test_mask) |
| + if (!(test_mask & marks_mask & ~marks_ignored_mask)) |
| return 0; |
| |
| return group->ops->handle_event(group, to_tell, inode_mark, |