summaryrefslogtreecommitdiffstats
path: root/fs/notify/notification.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-01-28 18:53:22 +0100
committerJan Kara <jack@suse.cz>2014-01-29 13:57:10 +0100
commit83c0e1b442b488571f4fef4a91c2fe52eed6c705 (patch)
treeb29a85223f2e5e166f075266edb1bf2e0ef5cf57 /fs/notify/notification.c
parentfanotify: Fix use after free in mask checking (diff)
downloadlinux-83c0e1b442b488571f4fef4a91c2fe52eed6c705.tar.xz
linux-83c0e1b442b488571f4fef4a91c2fe52eed6c705.zip
fsnotify: Do not return merged event from fsnotify_add_notify_event()
The event returned from fsnotify_add_notify_event() cannot ever be used safely as the event may be freed by the time the function returns (after dropping notification_mutex). So change the prototype to just return whether the event was added or merged into some existing event. Reported-and-tested-by: Jiri Kosina <jkosina@suse.cz> Reported-and-tested-by: Dave Jones <davej@fedoraproject.org> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/notify/notification.c')
-rw-r--r--fs/notify/notification.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 952237b8e2d2..18b3c4427dca 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -79,15 +79,15 @@ 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. If the event is successfully added to the
- * group's notification queue, a reference is taken on event.
+ * 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.
*/
-struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
- struct fsnotify_event *event,
- struct fsnotify_event *(*merge)(struct list_head *,
- struct fsnotify_event *))
+int fsnotify_add_notify_event(struct fsnotify_group *group,
+ struct fsnotify_event *event,
+ int (*merge)(struct list_head *,
+ struct fsnotify_event *))
{
- struct fsnotify_event *return_event = NULL;
+ int ret = 0;
struct list_head *list = &group->notification_list;
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -98,14 +98,14 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
/* Queue overflow event only if it isn't already queued */
if (list_empty(&group->overflow_event.list))
event = &group->overflow_event;
- return_event = event;
+ ret = 1;
}
if (!list_empty(list) && merge) {
- return_event = merge(list, event);
- if (return_event) {
+ ret = merge(list, event);
+ if (ret) {
mutex_unlock(&group->notification_mutex);
- return return_event;
+ return ret;
}
}
@@ -115,7 +115,7 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
wake_up(&group->notification_waitq);
kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
- return return_event;
+ return ret;
}
/*