Skip to content

Commit 8581679

Browse files
committed
fanotify: Fix use after free for permission events
Currently struct fanotify_event_info has been destroyed immediately after reporting its contents to userspace. However that is wrong for permission events because those need to stay around until userspace provides response which is filled back in fanotify_event_info. So change to code to free permission events only after we have got the response from userspace. Reported-and-tested-by: Jiri Kosina <[email protected]> Reported-and-tested-by: Dave Jones <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 83c0e1b commit 8581679

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

fs/notify/fanotify/fanotify.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,17 @@ static int fanotify_handle_event(struct fsnotify_group *group,
192192

193193
ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
194194
if (ret) {
195+
BUG_ON(mask & FAN_ALL_PERM_EVENTS);
195196
/* Our event wasn't used in the end. Free it. */
196197
fsnotify_destroy_event(group, fsn_event);
197198
ret = 0;
198199
}
199200

200201
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
201-
if (mask & FAN_ALL_PERM_EVENTS)
202+
if (mask & FAN_ALL_PERM_EVENTS) {
202203
ret = fanotify_get_response_from_access(group, event);
204+
fsnotify_destroy_event(group, fsn_event);
205+
}
203206
#endif
204207
return ret;
205208
}

fs/notify/fanotify/fanotify.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
extern struct kmem_cache *fanotify_event_cachep;
66

7+
/*
8+
* Lifetime of the structure differs for normal and permission events. In both
9+
* cases the structure is allocated in fanotify_handle_event(). For normal
10+
* events the structure is freed immediately after reporting it to userspace.
11+
* For permission events we free it only after we receive response from
12+
* userspace.
13+
*/
714
struct fanotify_event_info {
815
struct fsnotify_event fse;
916
/*

fs/notify/fanotify/fanotify_user.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,12 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
319319
if (IS_ERR(kevent))
320320
break;
321321
ret = copy_event_to_user(group, kevent, buf);
322-
fsnotify_destroy_event(group, kevent);
322+
/*
323+
* Permission events get destroyed after we
324+
* receive response
325+
*/
326+
if (!(kevent->mask & FAN_ALL_PERM_EVENTS))
327+
fsnotify_destroy_event(group, kevent);
323328
if (ret < 0)
324329
break;
325330
buf += ret;

0 commit comments

Comments
 (0)