diff options
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 5 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify.h | 7 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 7 |
3 files changed, 17 insertions, 2 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index c7e5e8f54748..0e792f5e3147 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -192,14 +192,17 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
192 | 192 | ||
193 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); | 193 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); |
194 | if (ret) { | 194 | if (ret) { |
195 | BUG_ON(mask & FAN_ALL_PERM_EVENTS); | ||
195 | /* Our event wasn't used in the end. Free it. */ | 196 | /* Our event wasn't used in the end. Free it. */ |
196 | fsnotify_destroy_event(group, fsn_event); | 197 | fsnotify_destroy_event(group, fsn_event); |
197 | ret = 0; | 198 | ret = 0; |
198 | } | 199 | } |
199 | 200 | ||
200 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 201 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
201 | if (mask & FAN_ALL_PERM_EVENTS) | 202 | if (mask & FAN_ALL_PERM_EVENTS) { |
202 | ret = fanotify_get_response_from_access(group, event); | 203 | ret = fanotify_get_response_from_access(group, event); |
204 | fsnotify_destroy_event(group, fsn_event); | ||
205 | } | ||
203 | #endif | 206 | #endif |
204 | return ret; | 207 | return ret; |
205 | } | 208 | } |
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h index 0e90174a116a..32a2f034fb94 100644 --- a/fs/notify/fanotify/fanotify.h +++ b/fs/notify/fanotify/fanotify.h | |||
@@ -4,6 +4,13 @@ | |||
4 | 4 | ||
5 | extern struct kmem_cache *fanotify_event_cachep; | 5 | extern struct kmem_cache *fanotify_event_cachep; |
6 | 6 | ||
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 | */ | ||
7 | struct fanotify_event_info { | 14 | struct fanotify_event_info { |
8 | struct fsnotify_event fse; | 15 | struct fsnotify_event fse; |
9 | /* | 16 | /* |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 1fd66abe5740..b6175fa11bf8 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -319,7 +319,12 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, | |||
319 | if (IS_ERR(kevent)) | 319 | if (IS_ERR(kevent)) |
320 | break; | 320 | break; |
321 | ret = copy_event_to_user(group, kevent, buf); | 321 | 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); | ||
323 | if (ret < 0) | 328 | if (ret < 0) |
324 | break; | 329 | break; |
325 | buf += ret; | 330 | buf += ret; |