fanotify: Handle overflow in case of permission events

If the event queue overflows when we are handling permission event, we
will never get response from userspace. So we must avoid waiting for it.
Change fsnotify_add_notify_event() to return whether overflow has
happened so that we can detect it in fanotify_handle_event() and act
accordingly.

Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
Jan Kara 2014-02-21 19:07:54 +01:00
Родитель 2513190a92
Коммит 482ef06c5e
2 изменённых файлов: 14 добавлений и 6 удалений

Просмотреть файл

@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group,
ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
if (ret) {
BUG_ON(mask & FAN_ALL_PERM_EVENTS);
/* Permission events shouldn't be merged */
BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS);
/* Our event wasn't used in the end. Free it. */
fsnotify_destroy_event(group, fsn_event);
ret = 0;
return 0;
}
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS

Просмотреть файл

@ -80,7 +80,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
/*
* Add an event to the group notification queue. The group can later pull this
* event off the queue to deal with. The function returns 0 if the event was
* added to the queue, 1 if the event was merged with some other queued event.
* added to the queue, 1 if the event was merged with some other queued event,
* 2 if the queue of events has overflown.
*/
int fsnotify_add_notify_event(struct fsnotify_group *group,
struct fsnotify_event *event,
@ -95,10 +96,14 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
mutex_lock(&group->notification_mutex);
if (group->q_len >= group->max_events) {
ret = 2;
/* Queue overflow event only if it isn't already queued */
if (list_empty(&group->overflow_event.list))
event = &group->overflow_event;
ret = 1;
if (!list_empty(&group->overflow_event.list)) {
mutex_unlock(&group->notification_mutex);
return ret;
}
event = &group->overflow_event;
goto queue;
}
if (!list_empty(list) && merge) {
@ -109,6 +114,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
}
}
queue:
group->q_len++;
list_add_tail(&event->list, list);
mutex_unlock(&group->notification_mutex);