summaryrefslogtreecommitdiff
path: root/fs/notify/fanotify/fanotify_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fanotify/fanotify_user.c')
-rw-r--r--fs/notify/fanotify/fanotify_user.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 3fdc8a3e1134..b13992a41bd9 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -66,7 +66,7 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
/* held the notification_mutex the whole time, so this is the
* same event we peeked above */
- return fsnotify_remove_notify_event(group);
+ return fsnotify_remove_first_event(group);
}
static int create_fd(struct fsnotify_group *group,
@@ -359,6 +359,11 @@ static int fanotify_release(struct inode *ignored, struct file *file)
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
struct fanotify_perm_event_info *event, *next;
+ /*
+ * There may be still new events arriving in the notification queue
+ * but since userspace cannot use fanotify fd anymore, no event can
+ * enter or leave access_list by now.
+ */
spin_lock(&group->fanotify_data.access_lock);
atomic_inc(&group->fanotify_data.bypass_perm);
@@ -373,6 +378,13 @@ static int fanotify_release(struct inode *ignored, struct file *file)
}
spin_unlock(&group->fanotify_data.access_lock);
+ /*
+ * Since bypass_perm is set, newly queued events will not wait for
+ * access response. Wake up the already sleeping ones now.
+ * synchronize_srcu() in fsnotify_destroy_group() will wait for all
+ * processes sleeping in fanotify_handle_event() waiting for access
+ * response and thus also for all permission events to be freed.
+ */
wake_up(&group->fanotify_data.access_waitq);
#endif