diff options
author | Jan Kara <jack@suse.cz> | 2014-01-28 12:53:22 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2014-01-29 07:57:10 -0500 |
commit | 83c0e1b442b488571f4fef4a91c2fe52eed6c705 (patch) | |
tree | b29a85223f2e5e166f075266edb1bf2e0ef5cf57 /fs/notify/fanotify | |
parent | 13116dfd13c8c9d60ea04ece13419af2de8e2e37 (diff) |
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/fanotify')
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 18 |
1 files changed, 7 insertions, 11 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index cc78e2fbc8e4..c7e5e8f54748 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -28,8 +28,7 @@ static bool should_merge(struct fsnotify_event *old_fsn, | |||
28 | } | 28 | } |
29 | 29 | ||
30 | /* and the list better be locked by something too! */ | 30 | /* and the list better be locked by something too! */ |
31 | static struct fsnotify_event *fanotify_merge(struct list_head *list, | 31 | static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) |
32 | struct fsnotify_event *event) | ||
33 | { | 32 | { |
34 | struct fsnotify_event *test_event; | 33 | struct fsnotify_event *test_event; |
35 | bool do_merge = false; | 34 | bool do_merge = false; |
@@ -43,7 +42,7 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list, | |||
43 | * one we should check for permission response. | 42 | * one we should check for permission response. |
44 | */ | 43 | */ |
45 | if (event->mask & FAN_ALL_PERM_EVENTS) | 44 | if (event->mask & FAN_ALL_PERM_EVENTS) |
46 | return NULL; | 45 | return 0; |
47 | #endif | 46 | #endif |
48 | 47 | ||
49 | list_for_each_entry_reverse(test_event, list, list) { | 48 | list_for_each_entry_reverse(test_event, list, list) { |
@@ -54,10 +53,10 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list, | |||
54 | } | 53 | } |
55 | 54 | ||
56 | if (!do_merge) | 55 | if (!do_merge) |
57 | return NULL; | 56 | return 0; |
58 | 57 | ||
59 | test_event->mask |= event->mask; | 58 | test_event->mask |= event->mask; |
60 | return test_event; | 59 | return 1; |
61 | } | 60 | } |
62 | 61 | ||
63 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 62 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
@@ -153,7 +152,6 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
153 | int ret = 0; | 152 | int ret = 0; |
154 | struct fanotify_event_info *event; | 153 | struct fanotify_event_info *event; |
155 | struct fsnotify_event *fsn_event; | 154 | struct fsnotify_event *fsn_event; |
156 | struct fsnotify_event *notify_fsn_event; | ||
157 | 155 | ||
158 | BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS); | 156 | BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS); |
159 | BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY); | 157 | BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY); |
@@ -192,13 +190,11 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
192 | event->response = 0; | 190 | event->response = 0; |
193 | #endif | 191 | #endif |
194 | 192 | ||
195 | notify_fsn_event = fsnotify_add_notify_event(group, fsn_event, | 193 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); |
196 | fanotify_merge); | 194 | if (ret) { |
197 | if (notify_fsn_event) { | ||
198 | /* Our event wasn't used in the end. Free it. */ | 195 | /* Our event wasn't used in the end. Free it. */ |
199 | fsnotify_destroy_event(group, fsn_event); | 196 | fsnotify_destroy_event(group, fsn_event); |
200 | if (IS_ERR(notify_fsn_event)) | 197 | ret = 0; |
201 | return PTR_ERR(notify_fsn_event); | ||
202 | } | 198 | } |
203 | 199 | ||
204 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 200 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |