diff options
Diffstat (limited to 'fs/notify/fanotify/fanotify.c')
| -rw-r--r-- | fs/notify/fanotify/fanotify.c | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index dc638f786d5c..ee9cb3795c2b 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
| @@ -60,8 +60,8 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 62 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
| 63 | static int fanotify_get_response_from_access(struct fsnotify_group *group, | 63 | static int fanotify_get_response(struct fsnotify_group *group, |
| 64 | struct fanotify_event_info *event) | 64 | struct fanotify_perm_event_info *event) |
| 65 | { | 65 | { |
| 66 | int ret; | 66 | int ret; |
| 67 | 67 | ||
| @@ -142,6 +142,40 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
| 142 | return false; | 142 | return false; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | struct fanotify_event_info *fanotify_alloc_event(struct inode *inode, u32 mask, | ||
| 146 | struct path *path) | ||
| 147 | { | ||
| 148 | struct fanotify_event_info *event; | ||
| 149 | |||
| 150 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | ||
| 151 | if (mask & FAN_ALL_PERM_EVENTS) { | ||
| 152 | struct fanotify_perm_event_info *pevent; | ||
| 153 | |||
| 154 | pevent = kmem_cache_alloc(fanotify_perm_event_cachep, | ||
| 155 | GFP_KERNEL); | ||
| 156 | if (!pevent) | ||
| 157 | return NULL; | ||
| 158 | event = &pevent->fae; | ||
| 159 | pevent->response = 0; | ||
| 160 | goto init; | ||
| 161 | } | ||
| 162 | #endif | ||
| 163 | event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); | ||
| 164 | if (!event) | ||
| 165 | return NULL; | ||
| 166 | init: __maybe_unused | ||
| 167 | fsnotify_init_event(&event->fse, inode, mask); | ||
| 168 | event->tgid = get_pid(task_tgid(current)); | ||
| 169 | if (path) { | ||
| 170 | event->path = *path; | ||
| 171 | path_get(&event->path); | ||
| 172 | } else { | ||
| 173 | event->path.mnt = NULL; | ||
| 174 | event->path.dentry = NULL; | ||
| 175 | } | ||
| 176 | return event; | ||
| 177 | } | ||
| 178 | |||
| 145 | static int fanotify_handle_event(struct fsnotify_group *group, | 179 | static int fanotify_handle_event(struct fsnotify_group *group, |
| 146 | struct inode *inode, | 180 | struct inode *inode, |
| 147 | struct fsnotify_mark *inode_mark, | 181 | struct fsnotify_mark *inode_mark, |
| @@ -171,25 +205,11 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
| 171 | pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, | 205 | pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode, |
| 172 | mask); | 206 | mask); |
| 173 | 207 | ||
| 174 | event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); | 208 | event = fanotify_alloc_event(inode, mask, data); |
| 175 | if (unlikely(!event)) | 209 | if (unlikely(!event)) |
| 176 | return -ENOMEM; | 210 | return -ENOMEM; |
| 177 | 211 | ||
| 178 | fsn_event = &event->fse; | 212 | 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); | 213 | ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge); |
| 194 | if (ret) { | 214 | if (ret) { |
| 195 | /* Permission events shouldn't be merged */ | 215 | /* Permission events shouldn't be merged */ |
| @@ -202,7 +222,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, | |||
| 202 | 222 | ||
| 203 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 223 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
| 204 | if (mask & FAN_ALL_PERM_EVENTS) { | 224 | if (mask & FAN_ALL_PERM_EVENTS) { |
| 205 | ret = fanotify_get_response_from_access(group, event); | 225 | ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event)); |
| 206 | fsnotify_destroy_event(group, fsn_event); | 226 | fsnotify_destroy_event(group, fsn_event); |
| 207 | } | 227 | } |
| 208 | #endif | 228 | #endif |
| @@ -225,6 +245,13 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event) | |||
| 225 | event = FANOTIFY_E(fsn_event); | 245 | event = FANOTIFY_E(fsn_event); |
| 226 | path_put(&event->path); | 246 | path_put(&event->path); |
| 227 | put_pid(event->tgid); | 247 | put_pid(event->tgid); |
| 248 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | ||
| 249 | if (fsn_event->mask & FAN_ALL_PERM_EVENTS) { | ||
| 250 | kmem_cache_free(fanotify_perm_event_cachep, | ||
| 251 | FANOTIFY_PE(fsn_event)); | ||
| 252 | return; | ||
| 253 | } | ||
| 254 | #endif | ||
| 228 | kmem_cache_free(fanotify_event_cachep, event); | 255 | kmem_cache_free(fanotify_event_cachep, event); |
| 229 | } | 256 | } |
| 230 | 257 | ||
