blob: 3c272f61d341822bfbb36f3be515176e2e0051dd [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -05002#include <linux/fanotify.h>
Eric Paris11637e42009-12-17 21:24:25 -05003#include <linux/fcntl.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05004#include <linux/file.h>
Eric Paris11637e42009-12-17 21:24:25 -05005#include <linux/fs.h>
Eric Paris52c923d2009-12-17 21:24:26 -05006#include <linux/anon_inodes.h>
Eric Paris11637e42009-12-17 21:24:25 -05007#include <linux/fsnotify_backend.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05008#include <linux/init.h>
Eric Parisa1014f12009-12-17 21:24:26 -05009#include <linux/mount.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050010#include <linux/namei.h>
Eric Parisa1014f12009-12-17 21:24:26 -050011#include <linux/poll.h>
Eric Paris11637e42009-12-17 21:24:25 -050012#include <linux/security.h>
13#include <linux/syscalls.h>
Tejun Heoe4e047a2010-05-20 01:36:28 +100014#include <linux/slab.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050015#include <linux/types.h>
Eric Parisa1014f12009-12-17 21:24:26 -050016#include <linux/uaccess.h>
Al Viro91c2e0b2013-03-05 20:10:59 -050017#include <linux/compat.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010018#include <linux/sched/signal.h>
Shakeel Buttd46eb14b2018-08-17 15:46:39 -070019#include <linux/memcontrol.h>
Amir Goldsteina8b13aa2019-01-10 19:04:36 +020020#include <linux/statfs.h>
21#include <linux/exportfs.h>
Eric Parisa1014f12009-12-17 21:24:26 -050022
23#include <asm/ioctls.h>
Eric Paris11637e42009-12-17 21:24:25 -050024
Al Viroc63181e2011-11-25 02:35:16 -050025#include "../../mount.h"
Cyrill Gorcunovbe771962012-12-17 16:05:12 -080026#include "../fdinfo.h"
Jan Kara7053aee2014-01-21 15:48:14 -080027#include "fanotify.h"
Al Viroc63181e2011-11-25 02:35:16 -050028
Eric Paris2529a0d2010-10-28 17:21:57 -040029#define FANOTIFY_DEFAULT_MAX_EVENTS 16384
Eric Parise7099d82010-10-28 17:21:57 -040030#define FANOTIFY_DEFAULT_MAX_MARKS 8192
Eric Paris4afeff82010-10-28 17:21:58 -040031#define FANOTIFY_DEFAULT_MAX_LISTENERS 128
Eric Paris2529a0d2010-10-28 17:21:57 -040032
Heinrich Schuchardt48149e92014-06-04 16:05:44 -070033/*
34 * All flags that may be specified in parameter event_f_flags of fanotify_init.
35 *
36 * Internal and external open flags are stored together in field f_flags of
37 * struct file. Only external open flags shall be allowed in event_f_flags.
38 * Internal flags like FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME shall be
39 * excluded.
40 */
41#define FANOTIFY_INIT_ALL_EVENT_F_BITS ( \
42 O_ACCMODE | O_APPEND | O_NONBLOCK | \
43 __O_SYNC | O_DSYNC | O_CLOEXEC | \
44 O_LARGEFILE | O_NOATIME )
45
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -050046extern const struct fsnotify_ops fanotify_fsnotify_ops;
Eric Paris11637e42009-12-17 21:24:25 -050047
Jan Kara054c6362016-12-21 18:06:12 +010048struct kmem_cache *fanotify_mark_cache __read_mostly;
Jan Kara7053aee2014-01-21 15:48:14 -080049struct kmem_cache *fanotify_event_cachep __read_mostly;
Jan Karaf0834412014-04-03 14:46:33 -070050struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
Eric Paris2a3edf82009-12-17 21:24:26 -050051
Amir Goldstein5e469c82019-01-10 19:04:35 +020052#define FANOTIFY_EVENT_ALIGN 4
53
54static int fanotify_event_info_len(struct fanotify_event *event)
55{
56 if (!fanotify_event_has_fid(event))
57 return 0;
58
59 return roundup(sizeof(struct fanotify_event_info_fid) +
60 sizeof(struct file_handle) + event->fh_len,
61 FANOTIFY_EVENT_ALIGN);
62}
63
Eric Parisa1014f12009-12-17 21:24:26 -050064/*
65 * Get an fsnotify notification event if one exists and is small
66 * enough to fit in "count". Return an error pointer if the count
Jan Kara40873282019-01-08 14:02:44 +010067 * is not large enough. When permission event is dequeued, its state is
68 * updated accordingly.
Eric Parisa1014f12009-12-17 21:24:26 -050069 */
70static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
71 size_t count)
72{
Amir Goldstein5e469c82019-01-10 19:04:35 +020073 size_t event_size = FAN_EVENT_METADATA_LEN;
Jan Kara8c554462019-01-08 13:52:31 +010074 struct fsnotify_event *fsn_event = NULL;
Eric Parisa1014f12009-12-17 21:24:26 -050075
76 pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
77
Jan Kara8c554462019-01-08 13:52:31 +010078 spin_lock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -050079 if (fsnotify_notify_queue_is_empty(group))
Jan Kara8c554462019-01-08 13:52:31 +010080 goto out;
Eric Parisa1014f12009-12-17 21:24:26 -050081
Amir Goldstein5e469c82019-01-10 19:04:35 +020082 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
Jan Kara8c554462019-01-08 13:52:31 +010083 event_size += fanotify_event_info_len(
84 FANOTIFY_E(fsnotify_peek_first_event(group)));
Amir Goldstein5e469c82019-01-10 19:04:35 +020085 }
86
Jan Kara8c554462019-01-08 13:52:31 +010087 if (event_size > count) {
88 fsn_event = ERR_PTR(-EINVAL);
89 goto out;
90 }
91 fsn_event = fsnotify_remove_first_event(group);
Jan Kara40873282019-01-08 14:02:44 +010092 if (fanotify_is_perm_event(FANOTIFY_E(fsn_event)->mask))
93 FANOTIFY_PE(fsn_event)->state = FAN_EVENT_REPORTED;
Jan Kara8c554462019-01-08 13:52:31 +010094out:
95 spin_unlock(&group->notification_lock);
96 return fsn_event;
Eric Parisa1014f12009-12-17 21:24:26 -050097}
98
Al Viro352e3b22012-08-19 12:30:45 -040099static int create_fd(struct fsnotify_group *group,
Amir Goldstein33913992019-01-10 19:04:32 +0200100 struct fanotify_event *event,
Jan Kara7053aee2014-01-21 15:48:14 -0800101 struct file **file)
Eric Parisa1014f12009-12-17 21:24:26 -0500102{
103 int client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500104 struct file *new_file;
105
Andreas Gruenbacher22aa4252009-12-17 21:24:26 -0500106 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
Eric Parisa1014f12009-12-17 21:24:26 -0500107
Yann Droneaud0b37e092014-10-09 15:24:40 -0700108 client_fd = get_unused_fd_flags(group->fanotify_data.f_flags);
Eric Parisa1014f12009-12-17 21:24:26 -0500109 if (client_fd < 0)
110 return client_fd;
111
Eric Parisa1014f12009-12-17 21:24:26 -0500112 /*
113 * we need a new file handle for the userspace program so it can read even if it was
114 * originally opened O_WRONLY.
115 */
Eric Parisa1014f12009-12-17 21:24:26 -0500116 /* it's possible this event was an overflow event. in that case dentry and mnt
117 * are NULL; That's fine, just don't call dentry open */
Al Viro765927b2012-06-26 21:58:53 +0400118 if (event->path.dentry && event->path.mnt)
119 new_file = dentry_open(&event->path,
Eric Paris80af2582010-07-28 10:18:37 -0400120 group->fanotify_data.f_flags | FMODE_NONOTIFY,
Eric Parisa1014f12009-12-17 21:24:26 -0500121 current_cred());
122 else
123 new_file = ERR_PTR(-EOVERFLOW);
124 if (IS_ERR(new_file)) {
125 /*
126 * we still send an event even if we can't open the file. this
127 * can happen when say tasks are gone and we try to open their
128 * /proc files or we try to open a WRONLY file like in sysfs
129 * we just send the errno to userspace since there isn't much
130 * else we can do.
131 */
132 put_unused_fd(client_fd);
133 client_fd = PTR_ERR(new_file);
134 } else {
Al Viro352e3b22012-08-19 12:30:45 -0400135 *file = new_file;
Eric Parisa1014f12009-12-17 21:24:26 -0500136 }
137
Andreas Gruenbacher22aa4252009-12-17 21:24:26 -0500138 return client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500139}
140
Jan Kara40873282019-01-08 14:02:44 +0100141/*
142 * Finish processing of permission event by setting it to ANSWERED state and
143 * drop group->notification_lock.
144 */
145static void finish_permission_event(struct fsnotify_group *group,
146 struct fanotify_perm_event *event,
147 unsigned int response)
148 __releases(&group->notification_lock)
149{
150 assert_spin_locked(&group->notification_lock);
151 event->response = response;
152 event->state = FAN_EVENT_ANSWERED;
153 spin_unlock(&group->notification_lock);
154}
155
Eric Parisb2d87902009-12-17 21:24:34 -0500156static int process_access_response(struct fsnotify_group *group,
157 struct fanotify_response *response_struct)
158{
Amir Goldstein33913992019-01-10 19:04:32 +0200159 struct fanotify_perm_event *event;
Jan Karaf0834412014-04-03 14:46:33 -0700160 int fd = response_struct->fd;
161 int response = response_struct->response;
Eric Parisb2d87902009-12-17 21:24:34 -0500162
163 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,
164 fd, response);
165 /*
166 * make sure the response is valid, if invalid we do nothing and either
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300167 * userspace can send a valid response or we will clean it up after the
Eric Parisb2d87902009-12-17 21:24:34 -0500168 * timeout
169 */
Steve Grubbde8cd832017-10-02 20:21:39 -0400170 switch (response & ~FAN_AUDIT) {
Eric Parisb2d87902009-12-17 21:24:34 -0500171 case FAN_ALLOW:
172 case FAN_DENY:
173 break;
174 default:
175 return -EINVAL;
176 }
177
178 if (fd < 0)
179 return -EINVAL;
180
Amir Goldstein96a71f22018-09-21 21:20:30 +0300181 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -0400182 return -EINVAL;
183
Jan Karaaf6a5112019-01-08 13:28:18 +0100184 spin_lock(&group->notification_lock);
185 list_for_each_entry(event, &group->fanotify_data.access_list,
186 fae.fse.list) {
187 if (event->fd != fd)
188 continue;
Eric Parisb2d87902009-12-17 21:24:34 -0500189
Jan Karaaf6a5112019-01-08 13:28:18 +0100190 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100191 finish_permission_event(group, event, response);
Jan Karaaf6a5112019-01-08 13:28:18 +0100192 wake_up(&group->fanotify_data.access_waitq);
193 return 0;
194 }
195 spin_unlock(&group->notification_lock);
Eric Parisb2d87902009-12-17 21:24:34 -0500196
Jan Karaaf6a5112019-01-08 13:28:18 +0100197 return -ENOENT;
Eric Parisb2d87902009-12-17 21:24:34 -0500198}
Eric Parisb2d87902009-12-17 21:24:34 -0500199
Amir Goldstein5e469c82019-01-10 19:04:35 +0200200static int copy_fid_to_user(struct fanotify_event *event, char __user *buf)
201{
202 struct fanotify_event_info_fid info = { };
203 struct file_handle handle = { };
204 size_t fh_len = event->fh_len;
205 size_t len = fanotify_event_info_len(event);
206
207 if (!len)
208 return 0;
209
210 if (WARN_ON_ONCE(len < sizeof(info) + sizeof(handle) + fh_len))
211 return -EFAULT;
212
213 /* Copy event info fid header followed by vaiable sized file handle */
214 info.hdr.info_type = FAN_EVENT_INFO_TYPE_FID;
215 info.hdr.len = len;
216 info.fsid = event->fid.fsid;
217 if (copy_to_user(buf, &info, sizeof(info)))
218 return -EFAULT;
219
220 buf += sizeof(info);
221 len -= sizeof(info);
222 handle.handle_type = event->fh_type;
223 handle.handle_bytes = fh_len;
224 if (copy_to_user(buf, &handle, sizeof(handle)))
225 return -EFAULT;
226
227 buf += sizeof(handle);
228 len -= sizeof(handle);
229 if (copy_to_user(buf, fanotify_event_fh(event), fh_len))
230 return -EFAULT;
231
232 /* Pad with 0's */
233 buf += fh_len;
234 len -= fh_len;
235 WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
236 if (len > 0 && clear_user(buf, len))
237 return -EFAULT;
238
239 return 0;
240}
241
Eric Parisa1014f12009-12-17 21:24:26 -0500242static ssize_t copy_event_to_user(struct fsnotify_group *group,
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200243 struct fsnotify_event *fsn_event,
Kees Cook5b03a472018-12-04 15:44:46 -0800244 char __user *buf, size_t count)
Eric Parisa1014f12009-12-17 21:24:26 -0500245{
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200246 struct fanotify_event_metadata metadata;
247 struct fanotify_event *event;
248 struct file *f = NULL;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200249 int ret, fd = FAN_NOFD;
Eric Parisa1014f12009-12-17 21:24:26 -0500250
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200251 pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event);
Eric Parisa1014f12009-12-17 21:24:26 -0500252
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200253 event = container_of(fsn_event, struct fanotify_event, fse);
254 metadata.event_len = FAN_EVENT_METADATA_LEN;
255 metadata.metadata_len = FAN_EVENT_METADATA_LEN;
256 metadata.vers = FANOTIFY_METADATA_VERSION;
257 metadata.reserved = 0;
258 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
259 metadata.pid = pid_vnr(event->pid);
Eric Parisa1014f12009-12-17 21:24:26 -0500260
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200261 if (fanotify_event_has_path(event)) {
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200262 fd = create_fd(group, event, &f);
263 if (fd < 0)
264 return fd;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200265 } else if (fanotify_event_has_fid(event)) {
266 metadata.event_len += fanotify_event_info_len(event);
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200267 }
268 metadata.fd = fd;
269
Al Viro352e3b22012-08-19 12:30:45 -0400270 ret = -EFAULT;
Kees Cook5b03a472018-12-04 15:44:46 -0800271 /*
272 * Sanity check copy size in case get_one_event() and
273 * fill_event_metadata() event_len sizes ever get out of sync.
274 */
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200275 if (WARN_ON_ONCE(metadata.event_len > count))
Al Viro352e3b22012-08-19 12:30:45 -0400276 goto out_close_fd;
277
Amir Goldstein5e469c82019-01-10 19:04:35 +0200278 if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN))
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200279 goto out_close_fd;
280
281 if (fanotify_is_perm_event(event->mask))
282 FANOTIFY_PE(fsn_event)->fd = fd;
Eric Parisb2d87902009-12-17 21:24:34 -0500283
Amir Goldstein5e469c82019-01-10 19:04:35 +0200284 if (fanotify_event_has_path(event)) {
Al Viro3587b1b2012-11-18 19:19:00 +0000285 fd_install(fd, f);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200286 } else if (fanotify_event_has_fid(event)) {
287 ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN);
288 if (ret < 0)
289 return ret;
290 }
291
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200292 return metadata.event_len;
Eric Parisb2d87902009-12-17 21:24:34 -0500293
Eric Parisb2d87902009-12-17 21:24:34 -0500294out_close_fd:
Al Viro352e3b22012-08-19 12:30:45 -0400295 if (fd != FAN_NOFD) {
296 put_unused_fd(fd);
297 fput(f);
298 }
Eric Parisb2d87902009-12-17 21:24:34 -0500299 return ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500300}
301
302/* intofiy userspace file descriptor functions */
Al Viro076ccb72017-07-03 01:02:18 -0400303static __poll_t fanotify_poll(struct file *file, poll_table *wait)
Eric Parisa1014f12009-12-17 21:24:26 -0500304{
305 struct fsnotify_group *group = file->private_data;
Al Viro076ccb72017-07-03 01:02:18 -0400306 __poll_t ret = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500307
308 poll_wait(file, &group->notification_waitq, wait);
Jan Karac21dbe22016-10-07 16:56:52 -0700309 spin_lock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500310 if (!fsnotify_notify_queue_is_empty(group))
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800311 ret = EPOLLIN | EPOLLRDNORM;
Jan Karac21dbe22016-10-07 16:56:52 -0700312 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500313
314 return ret;
315}
316
317static ssize_t fanotify_read(struct file *file, char __user *buf,
318 size_t count, loff_t *pos)
319{
320 struct fsnotify_group *group;
321 struct fsnotify_event *kevent;
322 char __user *start;
323 int ret;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100324 DEFINE_WAIT_FUNC(wait, woken_wake_function);
Eric Parisa1014f12009-12-17 21:24:26 -0500325
326 start = buf;
327 group = file->private_data;
328
329 pr_debug("%s: group=%p\n", __func__, group);
330
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100331 add_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500332 while (1) {
Eric Parisa1014f12009-12-17 21:24:26 -0500333 kevent = get_one_event(group, count);
Jan Karad8aaab42014-04-03 14:46:35 -0700334 if (IS_ERR(kevent)) {
Eric Parisa1014f12009-12-17 21:24:26 -0500335 ret = PTR_ERR(kevent);
Jan Karad8aaab42014-04-03 14:46:35 -0700336 break;
337 }
338
339 if (!kevent) {
340 ret = -EAGAIN;
341 if (file->f_flags & O_NONBLOCK)
Eric Parisa1014f12009-12-17 21:24:26 -0500342 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700343
344 ret = -ERESTARTSYS;
345 if (signal_pending(current))
Eric Parisa1014f12009-12-17 21:24:26 -0500346 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700347
348 if (start != buf)
349 break;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100350
351 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
Eric Parisa1014f12009-12-17 21:24:26 -0500352 continue;
353 }
354
Kees Cook5b03a472018-12-04 15:44:46 -0800355 ret = copy_event_to_user(group, kevent, buf, count);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300356 if (unlikely(ret == -EOPENSTALE)) {
357 /*
358 * We cannot report events with stale fd so drop it.
359 * Setting ret to 0 will continue the event loop and
360 * do the right thing if there are no more events to
361 * read (i.e. return bytes read, -EAGAIN or wait).
362 */
363 ret = 0;
364 }
365
Jan Karad8aaab42014-04-03 14:46:35 -0700366 /*
367 * Permission events get queued to wait for response. Other
368 * events can be destroyed now.
369 */
Amir Goldsteina0a92d22019-01-10 19:04:31 +0200370 if (!fanotify_is_perm_event(FANOTIFY_E(kevent)->mask)) {
Jan Karad8aaab42014-04-03 14:46:35 -0700371 fsnotify_destroy_event(group, kevent);
Jan Karad5078162014-04-03 14:46:36 -0700372 } else {
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300373 if (ret <= 0) {
Jan Kara40873282019-01-08 14:02:44 +0100374 spin_lock(&group->notification_lock);
375 finish_permission_event(group,
376 FANOTIFY_PE(kevent), FAN_DENY);
Jan Karad5078162014-04-03 14:46:36 -0700377 wake_up(&group->fanotify_data.access_waitq);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300378 } else {
379 spin_lock(&group->notification_lock);
380 list_add_tail(&kevent->list,
381 &group->fanotify_data.access_list);
382 spin_unlock(&group->notification_lock);
Jan Karad5078162014-04-03 14:46:36 -0700383 }
Jan Karad5078162014-04-03 14:46:36 -0700384 }
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300385 if (ret < 0)
386 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700387 buf += ret;
388 count -= ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500389 }
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100390 remove_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500391
Eric Parisa1014f12009-12-17 21:24:26 -0500392 if (start != buf && ret != -EFAULT)
393 ret = buf - start;
394 return ret;
395}
396
Eric Parisb2d87902009-12-17 21:24:34 -0500397static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
398{
Eric Parisb2d87902009-12-17 21:24:34 -0500399 struct fanotify_response response = { .fd = -1, .response = -1 };
400 struct fsnotify_group *group;
401 int ret;
402
Miklos Szeredi6685df32017-10-30 21:14:56 +0100403 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
404 return -EINVAL;
405
Eric Parisb2d87902009-12-17 21:24:34 -0500406 group = file->private_data;
407
408 if (count > sizeof(response))
409 count = sizeof(response);
410
411 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
412
413 if (copy_from_user(&response, buf, count))
414 return -EFAULT;
415
416 ret = process_access_response(group, &response);
417 if (ret < 0)
418 count = ret;
419
420 return count;
Eric Parisb2d87902009-12-17 21:24:34 -0500421}
422
Eric Paris52c923d2009-12-17 21:24:26 -0500423static int fanotify_release(struct inode *ignored, struct file *file)
424{
425 struct fsnotify_group *group = file->private_data;
Jan Karaca6f8692019-01-09 13:21:01 +0100426 struct fanotify_perm_event *event;
Jan Kara96d41012016-09-19 14:44:30 -0700427 struct fsnotify_event *fsn_event;
Andrew Morton19ba54f2010-10-28 17:21:59 -0400428
Jan Kara5838d442014-08-06 16:03:28 -0700429 /*
Jan Kara96d41012016-09-19 14:44:30 -0700430 * Stop new events from arriving in the notification queue. since
431 * userspace cannot use fanotify fd anymore, no event can enter or
432 * leave access_list by now either.
433 */
434 fsnotify_group_stop_queueing(group);
435
436 /*
437 * Process all permission events on access_list and notification queue
438 * and simulate reply from userspace.
Jan Kara5838d442014-08-06 16:03:28 -0700439 */
Jan Kara073f6552016-10-07 16:56:55 -0700440 spin_lock(&group->notification_lock);
Jan Karaca6f8692019-01-09 13:21:01 +0100441 while (!list_empty(&group->fanotify_data.access_list)) {
442 event = list_first_entry(&group->fanotify_data.access_list,
443 struct fanotify_perm_event, fae.fse.list);
Jan Karaf0834412014-04-03 14:46:33 -0700444 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100445 finish_permission_event(group, event, FAN_ALLOW);
446 spin_lock(&group->notification_lock);
Eric Paris2eebf582010-08-18 12:25:50 -0400447 }
Eric Paris2eebf582010-08-18 12:25:50 -0400448
Jan Kara5838d442014-08-06 16:03:28 -0700449 /*
Jan Kara96d41012016-09-19 14:44:30 -0700450 * Destroy all non-permission events. For permission events just
451 * dequeue them and set the response. They will be freed once the
452 * response is consumed and fanotify_get_response() returns.
Jan Kara5838d442014-08-06 16:03:28 -0700453 */
Jan Kara96d41012016-09-19 14:44:30 -0700454 while (!fsnotify_notify_queue_is_empty(group)) {
455 fsn_event = fsnotify_remove_first_event(group);
Amir Goldsteina0a92d22019-01-10 19:04:31 +0200456 if (!(FANOTIFY_E(fsn_event)->mask & FANOTIFY_PERM_EVENTS)) {
Jan Karac21dbe22016-10-07 16:56:52 -0700457 spin_unlock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700458 fsnotify_destroy_event(group, fsn_event);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100459 } else {
Jan Kara40873282019-01-08 14:02:44 +0100460 finish_permission_event(group, FANOTIFY_PE(fsn_event),
461 FAN_ALLOW);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100462 }
Jan Kara40873282019-01-08 14:02:44 +0100463 spin_lock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700464 }
Jan Karac21dbe22016-10-07 16:56:52 -0700465 spin_unlock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700466
467 /* Response for all permission events it set, wakeup waiters */
Eric Paris2eebf582010-08-18 12:25:50 -0400468 wake_up(&group->fanotify_data.access_waitq);
Eric Paris0a6b6bd2011-10-14 17:43:39 -0400469
Eric Paris52c923d2009-12-17 21:24:26 -0500470 /* matches the fanotify_init->fsnotify_alloc_group */
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200471 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -0500472
473 return 0;
474}
475
Eric Parisa1014f12009-12-17 21:24:26 -0500476static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
477{
478 struct fsnotify_group *group;
Jan Kara7053aee2014-01-21 15:48:14 -0800479 struct fsnotify_event *fsn_event;
Eric Parisa1014f12009-12-17 21:24:26 -0500480 void __user *p;
481 int ret = -ENOTTY;
482 size_t send_len = 0;
483
484 group = file->private_data;
485
486 p = (void __user *) arg;
487
488 switch (cmd) {
489 case FIONREAD:
Jan Karac21dbe22016-10-07 16:56:52 -0700490 spin_lock(&group->notification_lock);
Jan Kara7053aee2014-01-21 15:48:14 -0800491 list_for_each_entry(fsn_event, &group->notification_list, list)
Eric Parisa1014f12009-12-17 21:24:26 -0500492 send_len += FAN_EVENT_METADATA_LEN;
Jan Karac21dbe22016-10-07 16:56:52 -0700493 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500494 ret = put_user(send_len, (int __user *) p);
495 break;
496 }
497
498 return ret;
499}
500
Eric Paris52c923d2009-12-17 21:24:26 -0500501static const struct file_operations fanotify_fops = {
Cyrill Gorcunovbe771962012-12-17 16:05:12 -0800502 .show_fdinfo = fanotify_show_fdinfo,
Eric Parisa1014f12009-12-17 21:24:26 -0500503 .poll = fanotify_poll,
504 .read = fanotify_read,
Eric Parisb2d87902009-12-17 21:24:34 -0500505 .write = fanotify_write,
Eric Paris52c923d2009-12-17 21:24:26 -0500506 .fasync = NULL,
507 .release = fanotify_release,
Eric Parisa1014f12009-12-17 21:24:26 -0500508 .unlocked_ioctl = fanotify_ioctl,
509 .compat_ioctl = fanotify_ioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200510 .llseek = noop_llseek,
Eric Paris52c923d2009-12-17 21:24:26 -0500511};
512
Eric Paris2a3edf82009-12-17 21:24:26 -0500513static int fanotify_find_path(int dfd, const char __user *filename,
514 struct path *path, unsigned int flags)
515{
516 int ret;
517
518 pr_debug("%s: dfd=%d filename=%p flags=%x\n", __func__,
519 dfd, filename, flags);
520
521 if (filename == NULL) {
Al Viro2903ff02012-08-28 12:52:22 -0400522 struct fd f = fdget(dfd);
Eric Paris2a3edf82009-12-17 21:24:26 -0500523
524 ret = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -0400525 if (!f.file)
Eric Paris2a3edf82009-12-17 21:24:26 -0500526 goto out;
527
528 ret = -ENOTDIR;
529 if ((flags & FAN_MARK_ONLYDIR) &&
Al Viro496ad9a2013-01-23 17:07:38 -0500530 !(S_ISDIR(file_inode(f.file)->i_mode))) {
Al Viro2903ff02012-08-28 12:52:22 -0400531 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500532 goto out;
533 }
534
Al Viro2903ff02012-08-28 12:52:22 -0400535 *path = f.file->f_path;
Eric Paris2a3edf82009-12-17 21:24:26 -0500536 path_get(path);
Al Viro2903ff02012-08-28 12:52:22 -0400537 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500538 } else {
539 unsigned int lookup_flags = 0;
540
541 if (!(flags & FAN_MARK_DONT_FOLLOW))
542 lookup_flags |= LOOKUP_FOLLOW;
543 if (flags & FAN_MARK_ONLYDIR)
544 lookup_flags |= LOOKUP_DIRECTORY;
545
546 ret = user_path_at(dfd, filename, lookup_flags, path);
547 if (ret)
548 goto out;
549 }
550
551 /* you can only watch an inode if you have read permissions on it */
552 ret = inode_permission(path->dentry->d_inode, MAY_READ);
553 if (ret)
554 path_put(path);
555out:
556 return ret;
557}
558
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500559static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
560 __u32 mask,
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200561 unsigned int flags,
562 int *destroy)
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500563{
Lino Sanfilippod2c18742015-02-10 14:08:24 -0800564 __u32 oldmask = 0;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500565
566 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500567 if (!(flags & FAN_MARK_IGNORED_MASK)) {
568 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +0300569 fsn_mark->mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500570 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +0300571 fsn_mark->ignored_mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500572 }
Lino Sanfilippoa1184492015-02-10 14:08:21 -0800573 *destroy = !(fsn_mark->mask | fsn_mark->ignored_mask);
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500574 spin_unlock(&fsn_mark->lock);
575
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500576 return mask & oldmask;
577}
578
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300579static int fanotify_remove_mark(struct fsnotify_group *group,
580 fsnotify_connp_t *connp, __u32 mask,
581 unsigned int flags)
Eric Paris88826272009-12-17 21:24:28 -0500582{
583 struct fsnotify_mark *fsn_mark = NULL;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500584 __u32 removed;
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200585 int destroy_mark;
Eric Paris88826272009-12-17 21:24:28 -0500586
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700587 mutex_lock(&group->mark_mutex);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300588 fsn_mark = fsnotify_find_mark(connp, group);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700589 if (!fsn_mark) {
590 mutex_unlock(&group->mark_mutex);
Eric Paris88826272009-12-17 21:24:28 -0500591 return -ENOENT;
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700592 }
Eric Paris88826272009-12-17 21:24:28 -0500593
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200594 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
595 &destroy_mark);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +0300596 if (removed & fsnotify_conn_mask(fsn_mark->connector))
597 fsnotify_recalc_mask(fsn_mark->connector);
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200598 if (destroy_mark)
Jan Kara4712e7222015-09-04 15:43:12 -0700599 fsnotify_detach_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700600 mutex_unlock(&group->mark_mutex);
Jan Kara4712e7222015-09-04 15:43:12 -0700601 if (destroy_mark)
602 fsnotify_free_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700603
Jan Karab1362ed2016-12-21 16:28:45 +0100604 /* matches the fsnotify_find_mark() */
Eric Paris2a3edf82009-12-17 21:24:26 -0500605 fsnotify_put_mark(fsn_mark);
Eric Paris2a3edf82009-12-17 21:24:26 -0500606 return 0;
607}
608
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300609static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
610 struct vfsmount *mnt, __u32 mask,
611 unsigned int flags)
612{
613 return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
614 mask, flags);
615}
616
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300617static int fanotify_remove_sb_mark(struct fsnotify_group *group,
618 struct super_block *sb, __u32 mask,
619 unsigned int flags)
620{
621 return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask, flags);
622}
623
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300624static int fanotify_remove_inode_mark(struct fsnotify_group *group,
625 struct inode *inode, __u32 mask,
626 unsigned int flags)
627{
628 return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
629 flags);
630}
631
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500632static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
633 __u32 mask,
634 unsigned int flags)
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500635{
Eric Paris192ca4d2010-10-28 17:21:59 -0400636 __u32 oldmask = -1;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500637
638 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500639 if (!(flags & FAN_MARK_IGNORED_MASK)) {
640 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +0300641 fsn_mark->mask |= mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500642 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +0300643 fsn_mark->ignored_mask |= mask;
Eric Parisc9778a92009-12-17 21:24:33 -0500644 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
645 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500646 }
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500647 spin_unlock(&fsn_mark->lock);
648
649 return mask & ~oldmask;
650}
651
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700652static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
Amir Goldsteinb812a9f2018-06-23 17:54:48 +0300653 fsnotify_connp_t *connp,
Amir Goldstein77115222019-01-10 19:04:37 +0200654 unsigned int type,
655 __kernel_fsid_t *fsid)
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700656{
657 struct fsnotify_mark *mark;
658 int ret;
659
660 if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
661 return ERR_PTR(-ENOSPC);
662
663 mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
664 if (!mark)
665 return ERR_PTR(-ENOMEM);
666
Jan Kara054c6362016-12-21 18:06:12 +0100667 fsnotify_init_mark(mark, group);
Amir Goldstein77115222019-01-10 19:04:37 +0200668 ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700669 if (ret) {
670 fsnotify_put_mark(mark);
671 return ERR_PTR(ret);
672 }
673
674 return mark;
675}
676
677
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300678static int fanotify_add_mark(struct fsnotify_group *group,
679 fsnotify_connp_t *connp, unsigned int type,
Amir Goldstein77115222019-01-10 19:04:37 +0200680 __u32 mask, unsigned int flags,
681 __kernel_fsid_t *fsid)
Eric Paris2a3edf82009-12-17 21:24:26 -0500682{
683 struct fsnotify_mark *fsn_mark;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500684 __u32 added;
Eric Paris2a3edf82009-12-17 21:24:26 -0500685
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700686 mutex_lock(&group->mark_mutex);
Amir Goldsteinb812a9f2018-06-23 17:54:48 +0300687 fsn_mark = fsnotify_find_mark(connp, group);
Eric Paris88826272009-12-17 21:24:28 -0500688 if (!fsn_mark) {
Amir Goldstein77115222019-01-10 19:04:37 +0200689 fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700690 if (IS_ERR(fsn_mark)) {
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700691 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700692 return PTR_ERR(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700693 }
Eric Paris88826272009-12-17 21:24:28 -0500694 }
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500695 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +0300696 if (added & ~fsnotify_conn_mask(fsn_mark->connector))
697 fsnotify_recalc_mask(fsn_mark->connector);
Jan Karac9747642016-12-14 13:53:46 +0100698 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700699
Lino Sanfilippofa218ab2010-11-09 18:18:16 +0100700 fsnotify_put_mark(fsn_mark);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700701 return 0;
Eric Paris88826272009-12-17 21:24:28 -0500702}
703
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300704static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
705 struct vfsmount *mnt, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +0200706 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300707{
708 return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +0200709 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300710}
711
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300712static int fanotify_add_sb_mark(struct fsnotify_group *group,
Amir Goldstein77115222019-01-10 19:04:37 +0200713 struct super_block *sb, __u32 mask,
714 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300715{
716 return fanotify_add_mark(group, &sb->s_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +0200717 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300718}
719
Andreas Gruenbacher52202df2009-12-17 21:24:28 -0500720static int fanotify_add_inode_mark(struct fsnotify_group *group,
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500721 struct inode *inode, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +0200722 unsigned int flags, __kernel_fsid_t *fsid)
Eric Paris88826272009-12-17 21:24:28 -0500723{
Eric Paris88826272009-12-17 21:24:28 -0500724 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
Eric Paris2a3edf82009-12-17 21:24:26 -0500725
Eric Paris5322a592010-10-28 17:21:57 -0400726 /*
727 * If some other task has this inode open for write we should not add
728 * an ignored mark, unless that ignored mark is supposed to survive
729 * modification changes anyway.
730 */
731 if ((flags & FAN_MARK_IGNORED_MASK) &&
732 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
Nikolay Borisovac9498d2018-12-11 10:27:23 +0200733 inode_is_open_for_write(inode))
Eric Paris5322a592010-10-28 17:21:57 -0400734 return 0;
735
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300736 return fanotify_add_mark(group, &inode->i_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +0200737 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
Eric Paris88826272009-12-17 21:24:28 -0500738}
Eric Paris2a3edf82009-12-17 21:24:26 -0500739
Eric Paris52c923d2009-12-17 21:24:26 -0500740/* fanotify syscalls */
Eric Paris08ae8932010-05-27 09:41:40 -0400741SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
Eric Paris11637e42009-12-17 21:24:25 -0500742{
Eric Paris52c923d2009-12-17 21:24:26 -0500743 struct fsnotify_group *group;
744 int f_flags, fd;
Eric Paris4afeff82010-10-28 17:21:58 -0400745 struct user_struct *user;
Amir Goldstein33913992019-01-10 19:04:32 +0200746 struct fanotify_event *oevent;
Eric Paris52c923d2009-12-17 21:24:26 -0500747
Amir Goldstein96a71f22018-09-21 21:20:30 +0300748 pr_debug("%s: flags=%x event_f_flags=%x\n",
749 __func__, flags, event_f_flags);
Eric Paris52c923d2009-12-17 21:24:26 -0500750
Eric Paris52c923d2009-12-17 21:24:26 -0500751 if (!capable(CAP_SYS_ADMIN))
Andreas Gruenbachera2f13ad2010-08-24 12:58:54 +0200752 return -EPERM;
Eric Paris52c923d2009-12-17 21:24:26 -0500753
Steve Grubbde8cd832017-10-02 20:21:39 -0400754#ifdef CONFIG_AUDITSYSCALL
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300755 if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -0400756#else
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300757 if (flags & ~FANOTIFY_INIT_FLAGS)
Steve Grubbde8cd832017-10-02 20:21:39 -0400758#endif
Eric Paris52c923d2009-12-17 21:24:26 -0500759 return -EINVAL;
760
Heinrich Schuchardt48149e92014-06-04 16:05:44 -0700761 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
762 return -EINVAL;
763
764 switch (event_f_flags & O_ACCMODE) {
765 case O_RDONLY:
766 case O_RDWR:
767 case O_WRONLY:
768 break;
769 default:
770 return -EINVAL;
771 }
772
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200773 if ((flags & FAN_REPORT_FID) &&
774 (flags & FANOTIFY_CLASS_BITS) != FAN_CLASS_NOTIF)
775 return -EINVAL;
776
Eric Paris4afeff82010-10-28 17:21:58 -0400777 user = get_current_user();
778 if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) {
779 free_uid(user);
780 return -EMFILE;
781 }
782
Eric Parisb2d87902009-12-17 21:24:34 -0500783 f_flags = O_RDWR | FMODE_NONOTIFY;
Eric Paris52c923d2009-12-17 21:24:26 -0500784 if (flags & FAN_CLOEXEC)
785 f_flags |= O_CLOEXEC;
786 if (flags & FAN_NONBLOCK)
787 f_flags |= O_NONBLOCK;
788
789 /* fsnotify_alloc_group takes a ref. Dropped in fanotify_release */
790 group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
Eric Paris26379192010-11-23 23:48:26 -0500791 if (IS_ERR(group)) {
792 free_uid(user);
Eric Paris52c923d2009-12-17 21:24:26 -0500793 return PTR_ERR(group);
Eric Paris26379192010-11-23 23:48:26 -0500794 }
Eric Paris52c923d2009-12-17 21:24:26 -0500795
Eric Paris4afeff82010-10-28 17:21:58 -0400796 group->fanotify_data.user = user;
Amir Goldstein96a71f22018-09-21 21:20:30 +0300797 group->fanotify_data.flags = flags;
Eric Paris4afeff82010-10-28 17:21:58 -0400798 atomic_inc(&user->fanotify_listeners);
Shakeel Buttd46eb14b2018-08-17 15:46:39 -0700799 group->memcg = get_mem_cgroup_from_mm(current->mm);
Eric Paris4afeff82010-10-28 17:21:58 -0400800
Amir Goldstein83b535d2019-01-10 19:04:42 +0200801 oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL,
802 FSNOTIFY_EVENT_NONE, NULL);
Jan Karaff57cd52014-02-21 19:14:11 +0100803 if (unlikely(!oevent)) {
804 fd = -ENOMEM;
805 goto out_destroy_group;
806 }
807 group->overflow_event = &oevent->fse;
Jan Karaff57cd52014-02-21 19:14:11 +0100808
Will Woods1e2ee492014-05-06 12:50:10 -0700809 if (force_o_largefile())
810 event_f_flags |= O_LARGEFILE;
Eric Paris80af2582010-07-28 10:18:37 -0400811 group->fanotify_data.f_flags = event_f_flags;
Eric Paris9e66e422009-12-17 21:24:34 -0500812 init_waitqueue_head(&group->fanotify_data.access_waitq);
813 INIT_LIST_HEAD(&group->fanotify_data.access_list);
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300814 switch (flags & FANOTIFY_CLASS_BITS) {
Eric Paris4231a232010-10-28 17:21:56 -0400815 case FAN_CLASS_NOTIF:
816 group->priority = FS_PRIO_0;
817 break;
818 case FAN_CLASS_CONTENT:
819 group->priority = FS_PRIO_1;
820 break;
821 case FAN_CLASS_PRE_CONTENT:
822 group->priority = FS_PRIO_2;
823 break;
824 default:
825 fd = -EINVAL;
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200826 goto out_destroy_group;
Eric Paris4231a232010-10-28 17:21:56 -0400827 }
Eric Pariscb2d4292009-12-17 21:24:34 -0500828
Eric Paris5dd03f52010-10-28 17:21:57 -0400829 if (flags & FAN_UNLIMITED_QUEUE) {
830 fd = -EPERM;
831 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200832 goto out_destroy_group;
Eric Paris5dd03f52010-10-28 17:21:57 -0400833 group->max_events = UINT_MAX;
834 } else {
835 group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS;
836 }
Eric Paris2529a0d2010-10-28 17:21:57 -0400837
Eric Parisac7e22d2010-10-28 17:21:58 -0400838 if (flags & FAN_UNLIMITED_MARKS) {
839 fd = -EPERM;
840 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200841 goto out_destroy_group;
Eric Parisac7e22d2010-10-28 17:21:58 -0400842 group->fanotify_data.max_marks = UINT_MAX;
843 } else {
844 group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
845 }
Eric Parise7099d82010-10-28 17:21:57 -0400846
Steve Grubbde8cd832017-10-02 20:21:39 -0400847 if (flags & FAN_ENABLE_AUDIT) {
848 fd = -EPERM;
849 if (!capable(CAP_AUDIT_WRITE))
850 goto out_destroy_group;
Steve Grubbde8cd832017-10-02 20:21:39 -0400851 }
852
Eric Paris52c923d2009-12-17 21:24:26 -0500853 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
854 if (fd < 0)
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200855 goto out_destroy_group;
Eric Paris52c923d2009-12-17 21:24:26 -0500856
857 return fd;
858
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200859out_destroy_group:
860 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -0500861 return fd;
Eric Paris11637e42009-12-17 21:24:25 -0500862}
Eric Parisbbaa4162009-12-17 21:24:26 -0500863
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200864/* Check if filesystem can encode a unique fid */
Amir Goldstein73072282019-01-10 19:04:39 +0200865static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200866{
Amir Goldstein73072282019-01-10 19:04:39 +0200867 __kernel_fsid_t root_fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200868 int err;
869
870 /*
871 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
872 */
Amir Goldstein73072282019-01-10 19:04:39 +0200873 err = vfs_get_fsid(path->dentry, fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200874 if (err)
875 return err;
876
Amir Goldstein73072282019-01-10 19:04:39 +0200877 if (!fsid->val[0] && !fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200878 return -ENODEV;
879
880 /*
881 * Make sure path is not inside a filesystem subvolume (e.g. btrfs)
882 * which uses a different fsid than sb root.
883 */
Amir Goldstein73072282019-01-10 19:04:39 +0200884 err = vfs_get_fsid(path->dentry->d_sb->s_root, &root_fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200885 if (err)
886 return err;
887
Amir Goldstein73072282019-01-10 19:04:39 +0200888 if (root_fsid.val[0] != fsid->val[0] ||
889 root_fsid.val[1] != fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +0200890 return -EXDEV;
891
892 /*
893 * We need to make sure that the file system supports at least
894 * encoding a file handle so user can use name_to_handle_at() to
895 * compare fid returned with event to the file handle of watched
896 * objects. However, name_to_handle_at() requires that the
897 * filesystem also supports decoding file handles.
898 */
899 if (!path->dentry->d_sb->s_export_op ||
900 !path->dentry->d_sb->s_export_op->fh_to_dentry)
901 return -EOPNOTSUPP;
902
903 return 0;
904}
905
Dominik Brodowski183caa32018-03-17 15:06:11 +0100906static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
907 int dfd, const char __user *pathname)
Eric Parisbbaa4162009-12-17 21:24:26 -0500908{
Eric Paris0ff21db2009-12-17 21:24:29 -0500909 struct inode *inode = NULL;
910 struct vfsmount *mnt = NULL;
Eric Paris2a3edf82009-12-17 21:24:26 -0500911 struct fsnotify_group *group;
Al Viro2903ff02012-08-28 12:52:22 -0400912 struct fd f;
Eric Paris2a3edf82009-12-17 21:24:26 -0500913 struct path path;
Amir Goldstein73072282019-01-10 19:04:39 +0200914 __kernel_fsid_t __fsid, *fsid = NULL;
Amir Goldsteinbdd5a462018-10-04 00:25:37 +0300915 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300916 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
Al Viro2903ff02012-08-28 12:52:22 -0400917 int ret;
Eric Paris2a3edf82009-12-17 21:24:26 -0500918
919 pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
920 __func__, fanotify_fd, flags, dfd, pathname, mask);
921
922 /* we only use the lower 32 bits as of right now. */
923 if (mask & ((__u64)0xffffffff << 32))
924 return -EINVAL;
925
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300926 if (flags & ~FANOTIFY_MARK_FLAGS)
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -0500927 return -EINVAL;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300928
929 switch (mark_type) {
930 case FAN_MARK_INODE:
931 case FAN_MARK_MOUNT:
932 case FAN_MARK_FILESYSTEM:
933 break;
934 default:
935 return -EINVAL;
936 }
937
Eric Paris4d926042009-12-17 21:24:34 -0500938 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
Lino Sanfilippo1734dee2010-11-22 18:46:33 +0100939 case FAN_MARK_ADD: /* fallthrough */
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -0500940 case FAN_MARK_REMOVE:
Lino Sanfilippo1734dee2010-11-22 18:46:33 +0100941 if (!mask)
942 return -EINVAL;
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -0700943 break;
Eric Paris4d926042009-12-17 21:24:34 -0500944 case FAN_MARK_FLUSH:
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300945 if (flags & ~(FANOTIFY_MARK_TYPE_BITS | FAN_MARK_FLUSH))
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -0700946 return -EINVAL;
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -0500947 break;
948 default:
949 return -EINVAL;
950 }
Eric Paris8fcd6522010-10-28 17:21:59 -0400951
Miklos Szeredi6685df32017-10-30 21:14:56 +0100952 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300953 valid_mask |= FANOTIFY_PERM_EVENTS;
Miklos Szeredi6685df32017-10-30 21:14:56 +0100954
955 if (mask & ~valid_mask)
Eric Paris2a3edf82009-12-17 21:24:26 -0500956 return -EINVAL;
957
Al Viro2903ff02012-08-28 12:52:22 -0400958 f = fdget(fanotify_fd);
959 if (unlikely(!f.file))
Eric Paris2a3edf82009-12-17 21:24:26 -0500960 return -EBADF;
961
962 /* verify that this is indeed an fanotify instance */
963 ret = -EINVAL;
Al Viro2903ff02012-08-28 12:52:22 -0400964 if (unlikely(f.file->f_op != &fanotify_fops))
Eric Paris2a3edf82009-12-17 21:24:26 -0500965 goto fput_and_out;
Al Viro2903ff02012-08-28 12:52:22 -0400966 group = f.file->private_data;
Eric Paris4231a232010-10-28 17:21:56 -0400967
968 /*
969 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
970 * allowed to set permissions events.
971 */
972 ret = -EINVAL;
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300973 if (mask & FANOTIFY_PERM_EVENTS &&
Eric Paris4231a232010-10-28 17:21:56 -0400974 group->priority == FS_PRIO_0)
975 goto fput_and_out;
Eric Paris2a3edf82009-12-17 21:24:26 -0500976
Amir Goldstein235328d2019-01-10 19:04:43 +0200977 /*
978 * Events with data type inode do not carry enough information to report
979 * event->fd, so we do not allow setting a mask for inode events unless
980 * group supports reporting fid.
981 * inode events are not supported on a mount mark, because they do not
982 * carry enough information (i.e. path) to be filtered by mount point.
983 */
984 if (mask & FANOTIFY_INODE_EVENTS &&
985 (!FAN_GROUP_FLAG(group, FAN_REPORT_FID) ||
986 mark_type == FAN_MARK_MOUNT))
987 goto fput_and_out;
988
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -0700989 if (flags & FAN_MARK_FLUSH) {
990 ret = 0;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300991 if (mark_type == FAN_MARK_MOUNT)
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -0700992 fsnotify_clear_vfsmount_marks_by_group(group);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300993 else if (mark_type == FAN_MARK_FILESYSTEM)
994 fsnotify_clear_sb_marks_by_group(group);
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -0700995 else
996 fsnotify_clear_inode_marks_by_group(group);
997 goto fput_and_out;
998 }
999
Eric Paris2a3edf82009-12-17 21:24:26 -05001000 ret = fanotify_find_path(dfd, pathname, &path, flags);
1001 if (ret)
1002 goto fput_and_out;
1003
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001004 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
Amir Goldstein73072282019-01-10 19:04:39 +02001005 ret = fanotify_test_fid(&path, &__fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001006 if (ret)
1007 goto path_put_and_out;
Amir Goldstein77115222019-01-10 19:04:37 +02001008
Amir Goldstein73072282019-01-10 19:04:39 +02001009 fsid = &__fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001010 }
1011
Eric Paris2a3edf82009-12-17 21:24:26 -05001012 /* inode held in place by reference to path; group by fget on fd */
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001013 if (mark_type == FAN_MARK_INODE)
Eric Paris0ff21db2009-12-17 21:24:29 -05001014 inode = path.dentry->d_inode;
1015 else
1016 mnt = path.mnt;
Eric Paris2a3edf82009-12-17 21:24:26 -05001017
1018 /* create/update an inode mark */
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001019 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001020 case FAN_MARK_ADD:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001021 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001022 ret = fanotify_add_vfsmount_mark(group, mnt, mask,
1023 flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001024 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001025 ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
1026 flags, fsid);
Eric Paris0ff21db2009-12-17 21:24:29 -05001027 else
Amir Goldstein77115222019-01-10 19:04:37 +02001028 ret = fanotify_add_inode_mark(group, inode, mask,
1029 flags, fsid);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001030 break;
1031 case FAN_MARK_REMOVE:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001032 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001033 ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
1034 flags);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001035 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001036 ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
1037 flags);
Andreas Gruenbacherf3640192009-12-17 21:24:29 -05001038 else
Amir Goldstein77115222019-01-10 19:04:37 +02001039 ret = fanotify_remove_inode_mark(group, inode, mask,
1040 flags);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001041 break;
1042 default:
1043 ret = -EINVAL;
1044 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001045
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001046path_put_and_out:
Eric Paris2a3edf82009-12-17 21:24:26 -05001047 path_put(&path);
1048fput_and_out:
Al Viro2903ff02012-08-28 12:52:22 -04001049 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -05001050 return ret;
Eric Parisbbaa4162009-12-17 21:24:26 -05001051}
Eric Paris2a3edf82009-12-17 21:24:26 -05001052
Dominik Brodowski183caa32018-03-17 15:06:11 +01001053SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags,
1054 __u64, mask, int, dfd,
1055 const char __user *, pathname)
1056{
1057 return do_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
1058}
1059
Al Viro91c2e0b2013-03-05 20:10:59 -05001060#ifdef CONFIG_COMPAT
1061COMPAT_SYSCALL_DEFINE6(fanotify_mark,
1062 int, fanotify_fd, unsigned int, flags,
1063 __u32, mask0, __u32, mask1, int, dfd,
1064 const char __user *, pathname)
1065{
Dominik Brodowski183caa32018-03-17 15:06:11 +01001066 return do_fanotify_mark(fanotify_fd, flags,
Al Viro91c2e0b2013-03-05 20:10:59 -05001067#ifdef __BIG_ENDIAN
Al Viro91c2e0b2013-03-05 20:10:59 -05001068 ((__u64)mask0 << 32) | mask1,
Heiko Carstens592f6b82014-01-27 17:07:19 -08001069#else
1070 ((__u64)mask1 << 32) | mask0,
Al Viro91c2e0b2013-03-05 20:10:59 -05001071#endif
1072 dfd, pathname);
1073}
1074#endif
1075
Eric Paris2a3edf82009-12-17 21:24:26 -05001076/*
Justin P. Mattockae0e47f2011-03-01 15:06:02 +01001077 * fanotify_user_setup - Our initialization function. Note that we cannot return
Eric Paris2a3edf82009-12-17 21:24:26 -05001078 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1079 * must result in panic().
1080 */
1081static int __init fanotify_user_setup(void)
1082{
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001083 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 8);
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001084 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
1085
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001086 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
1087 SLAB_PANIC|SLAB_ACCOUNT);
Amir Goldstein33913992019-01-10 19:04:32 +02001088 fanotify_event_cachep = KMEM_CACHE(fanotify_event, SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001089 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) {
1090 fanotify_perm_event_cachep =
Amir Goldstein33913992019-01-10 19:04:32 +02001091 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001092 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001093
1094 return 0;
1095}
1096device_initcall(fanotify_user_setup);