aboutsummaryrefslogtreecommitdiff
path: root/fs/notify/fanotify/fanotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fanotify/fanotify.c')
-rw-r--r--fs/notify/fanotify/fanotify.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 85366c78cc3..b04f88eed09 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -131,6 +131,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
+ BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -160,20 +161,21 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
__u32 event_mask, void *data, int data_type)
{
__u32 marks_mask, marks_ignored_mask;
+ struct path *path = data;
pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
"mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
inode_mark, vfsmnt_mark, event_mask, data, data_type);
- /* sorry, fanotify only gives a damn about files and dirs */
- if (!S_ISREG(to_tell->i_mode) &&
- !S_ISDIR(to_tell->i_mode))
- return false;
-
/* if we don't have enough info to send an event to userspace say no */
if (data_type != FSNOTIFY_EVENT_PATH)
return false;
+ /* sorry, fanotify only gives a damn about files and dirs */
+ if (!S_ISREG(path->dentry->d_inode->i_mode) &&
+ !S_ISDIR(path->dentry->d_inode->i_mode))
+ return false;
+
if (inode_mark && vfsmnt_mark) {
marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
@@ -194,16 +196,29 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
BUG();
}
+ if (S_ISDIR(path->dentry->d_inode->i_mode) &&
+ (marks_ignored_mask & FS_ISDIR))
+ return false;
+
if (event_mask & marks_mask & ~marks_ignored_mask)
return true;
return false;
}
+static void fanotify_free_group_priv(struct fsnotify_group *group)
+{
+ struct user_struct *user;
+
+ user = group->fanotify_data.user;
+ atomic_dec(&user->fanotify_listeners);
+ free_uid(user);
+}
+
const struct fsnotify_ops fanotify_fsnotify_ops = {
.handle_event = fanotify_handle_event,
.should_send_event = fanotify_should_send_event,
- .free_group_priv = NULL,
+ .free_group_priv = fanotify_free_group_priv,
.free_event_priv = NULL,
.freeing_mark = NULL,
};