aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-01-28 12:53:22 -0500
committerJan Kara <jack@suse.cz>2014-01-29 07:57:10 -0500
commit83c0e1b442b488571f4fef4a91c2fe52eed6c705 (patch)
treeb29a85223f2e5e166f075266edb1bf2e0ef5cf57 /fs/notify/fanotify
parent13116dfd13c8c9d60ea04ece13419af2de8e2e37 (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.c18
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! */
31static struct fsnotify_event *fanotify_merge(struct list_head *list, 31static 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