Skip to content

Commit

Permalink
fanotify: Release SRCU lock when waiting for userspace response
Browse files Browse the repository at this point in the history
When userspace task processing fanotify permission events screws up and
does not respond, fsnotify_mark_srcu SRCU is held indefinitely which
causes further hangs in the whole notification subsystem. Although we
cannot easily solve the problem of operations blocked waiting for
response from userspace, we can at least somewhat localize the damage by
dropping SRCU lock before waiting for userspace response and reacquiring
it when userspace responds.

Reviewed-by: Miklos Szeredi <[email protected]>
Reviewed-by: Amir Goldstein <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
  • Loading branch information
jankara committed Apr 10, 2017
1 parent 9385a84 commit 05f0e38
Showing 1 changed file with 15 additions and 2 deletions.
17 changes: 15 additions & 2 deletions fs/notify/fanotify/fanotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,26 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)

#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
static int fanotify_get_response(struct fsnotify_group *group,
struct fanotify_perm_event_info *event)
struct fanotify_perm_event_info *event,
struct fsnotify_iter_info *iter_info)
{
int ret;

pr_debug("%s: group=%p event=%p\n", __func__, group, event);

/*
* fsnotify_prepare_user_wait() fails if we race with mark deletion.
* Just let the operation pass in that case.
*/
if (!fsnotify_prepare_user_wait(iter_info)) {
event->response = FAN_ALLOW;
goto out;
}

wait_event(group->fanotify_data.access_waitq, event->response);

fsnotify_finish_user_wait(iter_info);
out:
/* userspace responded, convert to something usable */
switch (event->response) {
case FAN_ALLOW:
Expand Down Expand Up @@ -216,7 +228,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,

#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
if (mask & FAN_ALL_PERM_EVENTS) {
ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event));
ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event),
iter_info);
fsnotify_destroy_event(group, fsn_event);
}
#endif
Expand Down

0 comments on commit 05f0e38

Please sign in to comment.