Merge branch 'next' of git://git.infradead.org/users/pcmoore/selinux into next
[cascardo/linux.git] / fs / notify / fanotify / fanotify.c
index dc638f7..ee9cb37 100644 (file)
@@ -60,8 +60,8 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-static int fanotify_get_response_from_access(struct fsnotify_group *group,
-                                            struct fanotify_event_info *event)
+static int fanotify_get_response(struct fsnotify_group *group,
+                                struct fanotify_perm_event_info *event)
 {
        int ret;
 
@@ -142,6 +142,40 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
        return false;
 }
 
+struct fanotify_event_info *fanotify_alloc_event(struct inode *inode, u32 mask,
+                                                struct path *path)
+{
+       struct fanotify_event_info *event;
+
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (mask & FAN_ALL_PERM_EVENTS) {
+               struct fanotify_perm_event_info *pevent;
+
+               pevent = kmem_cache_alloc(fanotify_perm_event_cachep,
+                                         GFP_KERNEL);
+               if (!pevent)
+                       return NULL;
+               event = &pevent->fae;
+               pevent->response = 0;
+               goto init;
+       }
+#endif
+       event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
+       if (!event)
+               return NULL;
+init: __maybe_unused
+       fsnotify_init_event(&event->fse, inode, mask);
+       event->tgid = get_pid(task_tgid(current));
+       if (path) {
+               event->path = *path;
+               path_get(&event->path);
+       } else {
+               event->path.mnt = NULL;
+               event->path.dentry = NULL;
+       }
+       return event;
+}
+
 static int fanotify_handle_event(struct fsnotify_group *group,
                                 struct inode *inode,
                                 struct fsnotify_mark *inode_mark,
@@ -171,25 +205,11 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
                 mask);
 
-       event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
+       event = fanotify_alloc_event(inode, mask, data);
        if (unlikely(!event))
                return -ENOMEM;
 
        fsn_event = &event->fse;
-       fsnotify_init_event(fsn_event, inode, mask);
-       event->tgid = get_pid(task_tgid(current));
-       if (data_type == FSNOTIFY_EVENT_PATH) {
-               struct path *path = data;
-               event->path = *path;
-               path_get(&event->path);
-       } else {
-               event->path.mnt = NULL;
-               event->path.dentry = NULL;
-       }
-#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       event->response = 0;
-#endif
-
        ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
        if (ret) {
                /* Permission events shouldn't be merged */
@@ -202,7 +222,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
        if (mask & FAN_ALL_PERM_EVENTS) {
-               ret = fanotify_get_response_from_access(group, event);
+               ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event));
                fsnotify_destroy_event(group, fsn_event);
        }
 #endif
@@ -225,6 +245,13 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event)
        event = FANOTIFY_E(fsn_event);
        path_put(&event->path);
        put_pid(event->tgid);
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (fsn_event->mask & FAN_ALL_PERM_EVENTS) {
+               kmem_cache_free(fanotify_perm_event_cachep,
+                               FANOTIFY_PE(fsn_event));
+               return;
+       }
+#endif
        kmem_cache_free(fanotify_event_cachep, event);
 }