diff options
author | Jan Kara <jack@suse.cz> | 2014-01-28 18:53:22 +0100 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2014-01-29 13:57:10 +0100 |
commit | 83c0e1b442b488571f4fef4a91c2fe52eed6c705 (patch) | |
tree | b29a85223f2e5e166f075266edb1bf2e0ef5cf57 /fs/notify/notification.c | |
parent | fanotify: Fix use after free in mask checking (diff) | |
download | linux-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.c | 24 |
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; } /* |