linux/fs/notify
Lino Sanfilippo 09e5f14e57 fanotify: on group destroy allow all waiters to bypass permission check
When fanotify_release() is called, there may still be processes waiting for
access permission. Currently only processes for which an event has already been
queued into the groups access list will be woken up.  Processes for which no
event has been queued will continue to sleep and thus cause a deadlock when
fsnotify_put_group() is called.
Furthermore there is a race allowing further processes to be waiting on the
access wait queue after wake_up (if they arrive before clear_marks_by_group()
is called).
This patch corrects this by setting a flag to inform processes that the group
is about to be destroyed and thus not to wait for access permission.

[additional changelog from eparis]
Lets think about the 4 relevant code paths from the PoV of the
'operator' 'listener' 'responder' and 'closer'.  Where operator is the
process doing an action (like open/read) which could require permission.
Listener is the task (or in this case thread) slated with reading from
the fanotify file descriptor.  The 'responder' is the thread responsible
for responding to access requests.  'Closer' is the thread attempting to
close the fanotify file descriptor.

The 'operator' is going to end up in:
fanotify_handle_event()
  get_response_from_access()
    (THIS BLOCKS WAITING ON USERSPACE)

The 'listener' interesting code path
fanotify_read()
  copy_event_to_user()
    prepare_for_access_response()
      (THIS CREATES AN fanotify_response_event)

The 'responder' code path:
fanotify_write()
  process_access_response()
    (REMOVE A fanotify_response_event, SET RESPONSE, WAKE UP 'operator')

The 'closer':
fanotify_release()
  (SUPPOSED TO CLEAN UP THE REST OF THIS MESS)

What we have today is that in the closer we remove all of the
fanotify_response_events and set a bit so no more response events are
ever created in prepare_for_access_response().

The bug is that we never wake all of the operators up and tell them to
move along.  You fix that in fanotify_get_response_from_access().  You
also fix other operators which haven't gotten there yet.  So I agree
that's a good fix.
[/additional changelog from eparis]

[remove additional changes to minimize patch size]
[move initialization so it was inside CONFIG_FANOTIFY_PERMISSION]

Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Signed-off-by: Eric Paris <eparis@redhat.com>
2010-12-07 16:14:22 -05:00
..
dnotify fanotify: use both marks when possible 2010-07-28 10:18:55 -04:00
fanotify fanotify: on group destroy allow all waiters to bypass permission check 2010-12-07 16:14:22 -05:00
inotify fsnotify: rename FS_IN_ISDIR to FS_ISDIR 2010-10-28 17:22:15 -04:00
fsnotify.c fsnotify: call fsnotify_parent in perm events 2010-10-28 17:22:13 -04:00
fsnotify.h fsnotify: remove global fsnotify groups lists 2010-07-28 10:18:54 -04:00
group.c fsnotify: remove global fsnotify groups lists 2010-07-28 10:18:54 -04:00
inode_mark.c fsnotify: implement ordering between notifiers 2010-10-28 17:22:13 -04:00
Kconfig fanotify: allow fanotify to be built 2010-10-28 17:22:13 -04:00
Makefile fsnotify: vfsmount marks generic functions 2010-07-28 09:58:57 -04:00
mark.c fsnotify: remove global fsnotify groups lists 2010-07-28 10:18:54 -04:00
notification.c Revert "fsnotify: store struct file not struct path" 2010-08-12 14:23:04 -07:00
vfsmount_mark.c fsnotify: implement ordering between notifiers 2010-10-28 17:22:13 -04:00