]> Pileus Git - ~andy/linux/blob - fs/notify/fanotify/fanotify.c
ARM: at91: fix network interface ordering for sama5d36
[~andy/linux] / fs / notify / fanotify / fanotify.c
1 #include <linux/fanotify.h>
2 #include <linux/fdtable.h>
3 #include <linux/fsnotify_backend.h>
4 #include <linux/init.h>
5 #include <linux/jiffies.h>
6 #include <linux/kernel.h> /* UINT_MAX */
7 #include <linux/mount.h>
8 #include <linux/sched.h>
9 #include <linux/types.h>
10 #include <linux/wait.h>
11
12 #include "fanotify.h"
13
14 static bool should_merge(struct fsnotify_event *old_fsn,
15                          struct fsnotify_event *new_fsn)
16 {
17         struct fanotify_event_info *old, *new;
18
19         pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
20         old = FANOTIFY_E(old_fsn);
21         new = FANOTIFY_E(new_fsn);
22
23         if (old_fsn->inode == new_fsn->inode && old->tgid == new->tgid &&
24             old->path.mnt == new->path.mnt &&
25             old->path.dentry == new->path.dentry)
26                 return true;
27         return false;
28 }
29
30 /* and the list better be locked by something too! */
31 static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
32 {
33         struct fsnotify_event *test_event;
34         bool do_merge = false;
35
36         pr_debug("%s: list=%p event=%p\n", __func__, list, event);
37
38 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
39         /*
40          * Don't merge a permission event with any other event so that we know
41          * the event structure we have created in fanotify_handle_event() is the
42          * one we should check for permission response.
43          */
44         if (event->mask & FAN_ALL_PERM_EVENTS)
45                 return 0;
46 #endif
47
48         list_for_each_entry_reverse(test_event, list, list) {
49                 if (should_merge(test_event, event)) {
50                         do_merge = true;
51                         break;
52                 }
53         }
54
55         if (!do_merge)
56                 return 0;
57
58         test_event->mask |= event->mask;
59         return 1;
60 }
61
62 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
63 static int fanotify_get_response_from_access(struct fsnotify_group *group,
64                                              struct fanotify_event_info *event)
65 {
66         int ret;
67
68         pr_debug("%s: group=%p event=%p\n", __func__, group, event);
69
70         wait_event(group->fanotify_data.access_waitq, event->response ||
71                                 atomic_read(&group->fanotify_data.bypass_perm));
72
73         if (!event->response) /* bypass_perm set */
74                 return 0;
75
76         /* userspace responded, convert to something usable */
77         switch (event->response) {
78         case FAN_ALLOW:
79                 ret = 0;
80                 break;
81         case FAN_DENY:
82         default:
83                 ret = -EPERM;
84         }
85         event->response = 0;
86
87         pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
88                  group, event, ret);
89         
90         return ret;
91 }
92 #endif
93
94 static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
95                                        struct fsnotify_mark *vfsmnt_mark,
96                                        u32 event_mask,
97                                        void *data, int data_type)
98 {
99         __u32 marks_mask, marks_ignored_mask;
100         struct path *path = data;
101
102         pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p"
103                  " data_type=%d\n", __func__, inode_mark, vfsmnt_mark,
104                  event_mask, data, data_type);
105
106         /* if we don't have enough info to send an event to userspace say no */
107         if (data_type != FSNOTIFY_EVENT_PATH)
108                 return false;
109
110         /* sorry, fanotify only gives a damn about files and dirs */
111         if (!S_ISREG(path->dentry->d_inode->i_mode) &&
112             !S_ISDIR(path->dentry->d_inode->i_mode))
113                 return false;
114
115         if (inode_mark && vfsmnt_mark) {
116                 marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
117                 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
118         } else if (inode_mark) {
119                 /*
120                  * if the event is for a child and this inode doesn't care about
121                  * events on the child, don't send it!
122                  */
123                 if ((event_mask & FS_EVENT_ON_CHILD) &&
124                     !(inode_mark->mask & FS_EVENT_ON_CHILD))
125                         return false;
126                 marks_mask = inode_mark->mask;
127                 marks_ignored_mask = inode_mark->ignored_mask;
128         } else if (vfsmnt_mark) {
129                 marks_mask = vfsmnt_mark->mask;
130                 marks_ignored_mask = vfsmnt_mark->ignored_mask;
131         } else {
132                 BUG();
133         }
134
135         if (S_ISDIR(path->dentry->d_inode->i_mode) &&
136             (marks_ignored_mask & FS_ISDIR))
137                 return false;
138
139         if (event_mask & marks_mask & ~marks_ignored_mask)
140                 return true;
141
142         return false;
143 }
144
145 static int fanotify_handle_event(struct fsnotify_group *group,
146                                  struct inode *inode,
147                                  struct fsnotify_mark *inode_mark,
148                                  struct fsnotify_mark *fanotify_mark,
149                                  u32 mask, void *data, int data_type,
150                                  const unsigned char *file_name)
151 {
152         int ret = 0;
153         struct fanotify_event_info *event;
154         struct fsnotify_event *fsn_event;
155
156         BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
157         BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
158         BUILD_BUG_ON(FAN_CLOSE_NOWRITE != FS_CLOSE_NOWRITE);
159         BUILD_BUG_ON(FAN_CLOSE_WRITE != FS_CLOSE_WRITE);
160         BUILD_BUG_ON(FAN_OPEN != FS_OPEN);
161         BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD);
162         BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
163         BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
164         BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
165         BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
166
167         if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
168                                         data_type))
169                 return 0;
170
171         pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
172                  mask);
173
174         event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
175         if (unlikely(!event))
176                 return -ENOMEM;
177
178         fsn_event = &event->fse;
179         fsnotify_init_event(fsn_event, inode, mask);
180         event->tgid = get_pid(task_tgid(current));
181         if (data_type == FSNOTIFY_EVENT_PATH) {
182                 struct path *path = data;
183                 event->path = *path;
184                 path_get(&event->path);
185         } else {
186                 event->path.mnt = NULL;
187                 event->path.dentry = NULL;
188         }
189 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
190         event->response = 0;
191 #endif
192
193         ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
194         if (ret) {
195                 BUG_ON(mask & FAN_ALL_PERM_EVENTS);
196                 /* Our event wasn't used in the end. Free it. */
197                 fsnotify_destroy_event(group, fsn_event);
198                 ret = 0;
199         }
200
201 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
202         if (mask & FAN_ALL_PERM_EVENTS) {
203                 ret = fanotify_get_response_from_access(group, event);
204                 fsnotify_destroy_event(group, fsn_event);
205         }
206 #endif
207         return ret;
208 }
209
210 static void fanotify_free_group_priv(struct fsnotify_group *group)
211 {
212         struct user_struct *user;
213
214         user = group->fanotify_data.user;
215         atomic_dec(&user->fanotify_listeners);
216         free_uid(user);
217 }
218
219 static void fanotify_free_event(struct fsnotify_event *fsn_event)
220 {
221         struct fanotify_event_info *event;
222
223         event = FANOTIFY_E(fsn_event);
224         path_put(&event->path);
225         put_pid(event->tgid);
226         kmem_cache_free(fanotify_event_cachep, event);
227 }
228
229 const struct fsnotify_ops fanotify_fsnotify_ops = {
230         .handle_event = fanotify_handle_event,
231         .free_group_priv = fanotify_free_group_priv,
232         .free_event = fanotify_free_event,
233 };