aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify/fanotify_user.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-08-06 19:03:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 21:01:12 -0400
commit5838d4442bd5971687b72221736222637e03140d (patch)
treee639967a7baf1b1c6a0d1b5e0babc8083c7faad4 /fs/notify/fanotify/fanotify_user.c
parent8ba8fa917093510cdcb4ec8ff8b9603e1b525658 (diff)
fanotify: fix double free of pending permission events
Commit 85816794240b ("fanotify: Fix use after free for permission events") introduced a double free issue for permission events which are pending in group's notification queue while group is being destroyed. These events are freed from fanotify_handle_event() but they are not removed from groups notification queue and thus they get freed again from fsnotify_flush_notify(). Fix the problem by removing permission events from notification queue before freeing them if we skip processing access response. Also expand comments in fanotify_release() to explain group shutdown in detail. Fixes: 85816794240b9659e66e4d9b0df7c6e814e5f603 Signed-off-by: Jan Kara <jack@suse.cz> Reported-by: Douglas Leeder <douglas.leeder@sophos.com> Tested-by: Douglas Leeder <douglas.leeder@sophos.com> Reported-by: Heinrich Schuchard <xypron.glpk@gmx.de> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify/fanotify/fanotify_user.c')
-rw-r--r--fs/notify/fanotify/fanotify_user.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index fbf2210823ab..b13992a41bd9 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -359,6 +359,11 @@ static int fanotify_release(struct inode *ignored, struct file *file)
359#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 359#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
360 struct fanotify_perm_event_info *event, *next; 360 struct fanotify_perm_event_info *event, *next;
361 361
362 /*
363 * There may be still new events arriving in the notification queue
364 * but since userspace cannot use fanotify fd anymore, no event can
365 * enter or leave access_list by now.
366 */
362 spin_lock(&group->fanotify_data.access_lock); 367 spin_lock(&group->fanotify_data.access_lock);
363 368
364 atomic_inc(&group->fanotify_data.bypass_perm); 369 atomic_inc(&group->fanotify_data.bypass_perm);
@@ -373,6 +378,13 @@ static int fanotify_release(struct inode *ignored, struct file *file)
373 } 378 }
374 spin_unlock(&group->fanotify_data.access_lock); 379 spin_unlock(&group->fanotify_data.access_lock);
375 380
381 /*
382 * Since bypass_perm is set, newly queued events will not wait for
383 * access response. Wake up the already sleeping ones now.
384 * synchronize_srcu() in fsnotify_destroy_group() will wait for all
385 * processes sleeping in fanotify_handle_event() waiting for access
386 * response and thus also for all permission events to be freed.
387 */
376 wake_up(&group->fanotify_data.access_waitq); 388 wake_up(&group->fanotify_data.access_waitq);
377#endif 389#endif
378 390