blob: 2ff6bd85ba8f6abc70deaf9fd5192ef9cf2419b8 [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>
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +10004#include <linux/fdtable.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05005#include <linux/file.h>
Eric Paris11637e42009-12-17 21:24:25 -05006#include <linux/fs.h>
Eric Paris52c923d2009-12-17 21:24:26 -05007#include <linux/anon_inodes.h>
Eric Paris11637e42009-12-17 21:24:25 -05008#include <linux/fsnotify_backend.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05009#include <linux/init.h>
Eric Parisa1014f12009-12-17 21:24:26 -050010#include <linux/mount.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050011#include <linux/namei.h>
Eric Parisa1014f12009-12-17 21:24:26 -050012#include <linux/poll.h>
Eric Paris11637e42009-12-17 21:24:25 -050013#include <linux/security.h>
14#include <linux/syscalls.h>
Tejun Heoe4e047a2010-05-20 01:36:28 +100015#include <linux/slab.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050016#include <linux/types.h>
Eric Parisa1014f12009-12-17 21:24:26 -050017#include <linux/uaccess.h>
Al Viro91c2e0b2013-03-05 20:10:59 -050018#include <linux/compat.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010019#include <linux/sched/signal.h>
Shakeel Buttd46eb14b2018-08-17 15:46:39 -070020#include <linux/memcontrol.h>
Amir Goldsteina8b13aa2019-01-10 19:04:36 +020021#include <linux/statfs.h>
22#include <linux/exportfs.h>
Eric Parisa1014f12009-12-17 21:24:26 -050023
24#include <asm/ioctls.h>
Eric Paris11637e42009-12-17 21:24:25 -050025
Al Viroc63181e2011-11-25 02:35:16 -050026#include "../../mount.h"
Cyrill Gorcunovbe771962012-12-17 16:05:12 -080027#include "../fdinfo.h"
Jan Kara7053aee2014-01-21 15:48:14 -080028#include "fanotify.h"
Al Viroc63181e2011-11-25 02:35:16 -050029
Eric Paris2529a0d2010-10-28 17:21:57 -040030#define FANOTIFY_DEFAULT_MAX_EVENTS 16384
Amir Goldstein5b8fea62021-03-04 13:29:20 +020031#define FANOTIFY_OLD_DEFAULT_MAX_MARKS 8192
32#define FANOTIFY_DEFAULT_MAX_GROUPS 128
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -030033#define FANOTIFY_DEFAULT_FEE_POOL_SIZE 32
Amir Goldstein5b8fea62021-03-04 13:29:20 +020034
35/*
36 * Legacy fanotify marks limits (8192) is per group and we introduced a tunable
37 * limit of marks per user, similar to inotify. Effectively, the legacy limit
38 * of fanotify marks per user is <max marks per group> * <max groups per user>.
39 * This default limit (1M) also happens to match the increased limit of inotify
40 * max_user_watches since v5.10.
41 */
42#define FANOTIFY_DEFAULT_MAX_USER_MARKS \
43 (FANOTIFY_OLD_DEFAULT_MAX_MARKS * FANOTIFY_DEFAULT_MAX_GROUPS)
44
45/*
46 * Most of the memory cost of adding an inode mark is pinning the marked inode.
47 * The size of the filesystem inode struct is not uniform across filesystems,
48 * so double the size of a VFS inode is used as a conservative approximation.
49 */
50#define INODE_MARK_COST (2 * sizeof(struct inode))
51
52/* configurable via /proc/sys/fs/fanotify/ */
53static int fanotify_max_queued_events __read_mostly;
54
55#ifdef CONFIG_SYSCTL
56
57#include <linux/sysctl.h>
58
Sven Schnellef153c222021-07-30 08:28:54 +020059static long ft_zero = 0;
60static long ft_int_max = INT_MAX;
61
Xiaoming Ni7b9ad122022-01-21 22:11:59 -080062static struct ctl_table fanotify_table[] = {
Amir Goldstein5b8fea62021-03-04 13:29:20 +020063 {
64 .procname = "max_user_groups",
65 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS],
Sven Schnellef153c222021-07-30 08:28:54 +020066 .maxlen = sizeof(long),
Amir Goldstein5b8fea62021-03-04 13:29:20 +020067 .mode = 0644,
Sven Schnellef153c222021-07-30 08:28:54 +020068 .proc_handler = proc_doulongvec_minmax,
69 .extra1 = &ft_zero,
70 .extra2 = &ft_int_max,
Amir Goldstein5b8fea62021-03-04 13:29:20 +020071 },
72 {
73 .procname = "max_user_marks",
74 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS],
Sven Schnellef153c222021-07-30 08:28:54 +020075 .maxlen = sizeof(long),
Amir Goldstein5b8fea62021-03-04 13:29:20 +020076 .mode = 0644,
Sven Schnellef153c222021-07-30 08:28:54 +020077 .proc_handler = proc_doulongvec_minmax,
78 .extra1 = &ft_zero,
79 .extra2 = &ft_int_max,
Amir Goldstein5b8fea62021-03-04 13:29:20 +020080 },
81 {
82 .procname = "max_queued_events",
83 .data = &fanotify_max_queued_events,
84 .maxlen = sizeof(int),
85 .mode = 0644,
86 .proc_handler = proc_dointvec_minmax,
87 .extra1 = SYSCTL_ZERO
88 },
89 { }
90};
Xiaoming Ni7b9ad122022-01-21 22:11:59 -080091
92static void __init fanotify_sysctls_init(void)
93{
94 register_sysctl("fs/fanotify", fanotify_table);
95}
96#else
97#define fanotify_sysctls_init() do { } while (0)
Amir Goldstein5b8fea62021-03-04 13:29:20 +020098#endif /* CONFIG_SYSCTL */
Eric Paris2529a0d2010-10-28 17:21:57 -040099
Heinrich Schuchardt48149e92014-06-04 16:05:44 -0700100/*
101 * All flags that may be specified in parameter event_f_flags of fanotify_init.
102 *
103 * Internal and external open flags are stored together in field f_flags of
104 * struct file. Only external open flags shall be allowed in event_f_flags.
105 * Internal flags like FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME shall be
106 * excluded.
107 */
108#define FANOTIFY_INIT_ALL_EVENT_F_BITS ( \
109 O_ACCMODE | O_APPEND | O_NONBLOCK | \
110 __O_SYNC | O_DSYNC | O_CLOEXEC | \
111 O_LARGEFILE | O_NOATIME )
112
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -0500113extern const struct fsnotify_ops fanotify_fsnotify_ops;
Eric Paris11637e42009-12-17 21:24:25 -0500114
Jan Kara054c6362016-12-21 18:06:12 +0100115struct kmem_cache *fanotify_mark_cache __read_mostly;
Jan Kara7088f352020-03-24 17:04:20 +0100116struct kmem_cache *fanotify_fid_event_cachep __read_mostly;
117struct kmem_cache *fanotify_path_event_cachep __read_mostly;
Jan Karaf0834412014-04-03 14:46:33 -0700118struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
Eric Paris2a3edf82009-12-17 21:24:26 -0500119
Amir Goldstein5e469c82019-01-10 19:04:35 +0200120#define FANOTIFY_EVENT_ALIGN 4
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000121#define FANOTIFY_FID_INFO_HDR_LEN \
Amir Goldstein44d705b2020-03-19 17:10:22 +0200122 (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle))
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000123#define FANOTIFY_PIDFD_INFO_HDR_LEN \
124 sizeof(struct fanotify_event_info_pidfd)
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300125#define FANOTIFY_ERROR_INFO_LEN \
126 (sizeof(struct fanotify_event_info_error))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200127
Amir Goldstein44d705b2020-03-19 17:10:22 +0200128static int fanotify_fid_info_len(int fh_len, int name_len)
Amir Goldsteind766b552020-03-19 17:10:20 +0200129{
Amir Goldstein44d705b2020-03-19 17:10:22 +0200130 int info_len = fh_len;
131
132 if (name_len)
133 info_len += name_len + 1;
134
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000135 return roundup(FANOTIFY_FID_INFO_HDR_LEN + info_len,
136 FANOTIFY_EVENT_ALIGN);
Amir Goldsteind766b552020-03-19 17:10:20 +0200137}
138
Amir Goldstein7326e3822021-11-29 22:15:36 +0200139/* FAN_RENAME may have one or two dir+name info records */
140static int fanotify_dir_name_info_len(struct fanotify_event *event)
141{
142 struct fanotify_info *info = fanotify_event_info(event);
143 int dir_fh_len = fanotify_event_dir_fh_len(event);
144 int dir2_fh_len = fanotify_event_dir2_fh_len(event);
145 int info_len = 0;
146
147 if (dir_fh_len)
148 info_len += fanotify_fid_info_len(dir_fh_len,
149 info->name_len);
150 if (dir2_fh_len)
151 info_len += fanotify_fid_info_len(dir2_fh_len,
152 info->name2_len);
153
154 return info_len;
155}
156
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300157static size_t fanotify_event_len(unsigned int info_mode,
158 struct fanotify_event *event)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200159{
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300160 size_t event_len = FAN_EVENT_METADATA_LEN;
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300161 int fh_len;
Amir Goldstein929943b2020-07-16 11:42:28 +0300162 int dot_len = 0;
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300163
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300164 if (!info_mode)
165 return event_len;
166
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300167 if (fanotify_is_error_event(event->mask))
168 event_len += FANOTIFY_ERROR_INFO_LEN;
169
Amir Goldstein7326e3822021-11-29 22:15:36 +0200170 if (fanotify_event_has_any_dir_fh(event)) {
171 event_len += fanotify_dir_name_info_len(event);
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000172 } else if ((info_mode & FAN_REPORT_NAME) &&
173 (event->mask & FAN_ONDIR)) {
Amir Goldstein929943b2020-07-16 11:42:28 +0300174 /*
175 * With group flag FAN_REPORT_NAME, if name was not recorded in
176 * event on a directory, we will report the name ".".
177 */
178 dot_len = 1;
179 }
Jan Karaafc894c2020-03-24 16:55:37 +0100180
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000181 if (info_mode & FAN_REPORT_PIDFD)
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300182 event_len += FANOTIFY_PIDFD_INFO_HDR_LEN;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000183
Gabriel Krisman Bertazi4bd5a5c2021-10-25 16:27:38 -0300184 if (fanotify_event_has_object_fh(event)) {
185 fh_len = fanotify_event_object_fh_len(event);
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300186 event_len += fanotify_fid_info_len(fh_len, dot_len);
Gabriel Krisman Bertazi4bd5a5c2021-10-25 16:27:38 -0300187 }
Amir Goldstein5e469c82019-01-10 19:04:35 +0200188
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300189 return event_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200190}
191
Eric Parisa1014f12009-12-17 21:24:26 -0500192/*
Amir Goldstein94e00d22021-03-04 12:48:25 +0200193 * Remove an hashed event from merge hash table.
194 */
195static void fanotify_unhash_event(struct fsnotify_group *group,
196 struct fanotify_event *event)
197{
198 assert_spin_locked(&group->notification_lock);
199
200 pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
201 group, event, fanotify_event_hash_bucket(group, event));
202
203 if (WARN_ON_ONCE(hlist_unhashed(&event->merge_list)))
204 return;
205
206 hlist_del_init(&event->merge_list);
207}
208
209/*
Jan Kara7088f352020-03-24 17:04:20 +0100210 * Get an fanotify notification event if one exists and is small
Eric Parisa1014f12009-12-17 21:24:26 -0500211 * enough to fit in "count". Return an error pointer if the count
Jan Kara40873282019-01-08 14:02:44 +0100212 * is not large enough. When permission event is dequeued, its state is
213 * updated accordingly.
Eric Parisa1014f12009-12-17 21:24:26 -0500214 */
Jan Kara7088f352020-03-24 17:04:20 +0100215static struct fanotify_event *get_one_event(struct fsnotify_group *group,
Eric Parisa1014f12009-12-17 21:24:26 -0500216 size_t count)
217{
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300218 size_t event_size;
Jan Kara7088f352020-03-24 17:04:20 +0100219 struct fanotify_event *event = NULL;
Amir Goldstein6f731712021-03-04 12:48:22 +0200220 struct fsnotify_event *fsn_event;
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000221 unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
Eric Parisa1014f12009-12-17 21:24:26 -0500222
223 pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
224
Jan Kara8c554462019-01-08 13:52:31 +0100225 spin_lock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200226 fsn_event = fsnotify_peek_first_event(group);
227 if (!fsn_event)
Jan Kara8c554462019-01-08 13:52:31 +0100228 goto out;
Eric Parisa1014f12009-12-17 21:24:26 -0500229
Amir Goldstein6f731712021-03-04 12:48:22 +0200230 event = FANOTIFY_E(fsn_event);
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300231 event_size = fanotify_event_len(info_mode, event);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200232
Jan Kara8c554462019-01-08 13:52:31 +0100233 if (event_size > count) {
Jan Kara7088f352020-03-24 17:04:20 +0100234 event = ERR_PTR(-EINVAL);
Jan Kara8c554462019-01-08 13:52:31 +0100235 goto out;
236 }
Amir Goldstein6f731712021-03-04 12:48:22 +0200237
238 /*
239 * Held the notification_lock the whole time, so this is the
240 * same event we peeked above.
241 */
242 fsnotify_remove_first_event(group);
Jan Kara7088f352020-03-24 17:04:20 +0100243 if (fanotify_is_perm_event(event->mask))
244 FANOTIFY_PERM(event)->state = FAN_EVENT_REPORTED;
Amir Goldstein94e00d22021-03-04 12:48:25 +0200245 if (fanotify_is_hashed_event(event->mask))
246 fanotify_unhash_event(group, event);
Jan Kara8c554462019-01-08 13:52:31 +0100247out:
248 spin_unlock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100249 return event;
Eric Parisa1014f12009-12-17 21:24:26 -0500250}
251
Jan Karaa741c2f2020-03-24 15:27:52 +0100252static int create_fd(struct fsnotify_group *group, struct path *path,
Jan Kara7053aee2014-01-21 15:48:14 -0800253 struct file **file)
Eric Parisa1014f12009-12-17 21:24:26 -0500254{
255 int client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500256 struct file *new_file;
257
Yann Droneaud0b37e092014-10-09 15:24:40 -0700258 client_fd = get_unused_fd_flags(group->fanotify_data.f_flags);
Eric Parisa1014f12009-12-17 21:24:26 -0500259 if (client_fd < 0)
260 return client_fd;
261
Eric Parisa1014f12009-12-17 21:24:26 -0500262 /*
263 * we need a new file handle for the userspace program so it can read even if it was
264 * originally opened O_WRONLY.
265 */
Jan Karaa741c2f2020-03-24 15:27:52 +0100266 new_file = dentry_open(path,
267 group->fanotify_data.f_flags | FMODE_NONOTIFY,
268 current_cred());
Eric Parisa1014f12009-12-17 21:24:26 -0500269 if (IS_ERR(new_file)) {
270 /*
271 * we still send an event even if we can't open the file. this
272 * can happen when say tasks are gone and we try to open their
273 * /proc files or we try to open a WRONLY file like in sysfs
274 * we just send the errno to userspace since there isn't much
275 * else we can do.
276 */
277 put_unused_fd(client_fd);
278 client_fd = PTR_ERR(new_file);
279 } else {
Al Viro352e3b22012-08-19 12:30:45 -0400280 *file = new_file;
Eric Parisa1014f12009-12-17 21:24:26 -0500281 }
282
Andreas Gruenbacher22aa4252009-12-17 21:24:26 -0500283 return client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500284}
285
Jan Kara40873282019-01-08 14:02:44 +0100286/*
287 * Finish processing of permission event by setting it to ANSWERED state and
288 * drop group->notification_lock.
289 */
290static void finish_permission_event(struct fsnotify_group *group,
291 struct fanotify_perm_event *event,
292 unsigned int response)
293 __releases(&group->notification_lock)
294{
Jan Karafabf7f22019-01-08 15:18:02 +0100295 bool destroy = false;
296
Jan Kara40873282019-01-08 14:02:44 +0100297 assert_spin_locked(&group->notification_lock);
298 event->response = response;
Jan Karafabf7f22019-01-08 15:18:02 +0100299 if (event->state == FAN_EVENT_CANCELED)
300 destroy = true;
301 else
302 event->state = FAN_EVENT_ANSWERED;
Jan Kara40873282019-01-08 14:02:44 +0100303 spin_unlock(&group->notification_lock);
Jan Karafabf7f22019-01-08 15:18:02 +0100304 if (destroy)
305 fsnotify_destroy_event(group, &event->fae.fse);
Jan Kara40873282019-01-08 14:02:44 +0100306}
307
Eric Parisb2d87902009-12-17 21:24:34 -0500308static int process_access_response(struct fsnotify_group *group,
309 struct fanotify_response *response_struct)
310{
Amir Goldstein33913992019-01-10 19:04:32 +0200311 struct fanotify_perm_event *event;
Jan Karaf0834412014-04-03 14:46:33 -0700312 int fd = response_struct->fd;
313 int response = response_struct->response;
Eric Parisb2d87902009-12-17 21:24:34 -0500314
315 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,
316 fd, response);
317 /*
318 * make sure the response is valid, if invalid we do nothing and either
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300319 * userspace can send a valid response or we will clean it up after the
Eric Parisb2d87902009-12-17 21:24:34 -0500320 * timeout
321 */
Steve Grubbde8cd832017-10-02 20:21:39 -0400322 switch (response & ~FAN_AUDIT) {
Eric Parisb2d87902009-12-17 21:24:34 -0500323 case FAN_ALLOW:
324 case FAN_DENY:
325 break;
326 default:
327 return -EINVAL;
328 }
329
330 if (fd < 0)
331 return -EINVAL;
332
Amir Goldstein96a71f22018-09-21 21:20:30 +0300333 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -0400334 return -EINVAL;
335
Jan Karaaf6a5112019-01-08 13:28:18 +0100336 spin_lock(&group->notification_lock);
337 list_for_each_entry(event, &group->fanotify_data.access_list,
338 fae.fse.list) {
339 if (event->fd != fd)
340 continue;
Eric Parisb2d87902009-12-17 21:24:34 -0500341
Jan Karaaf6a5112019-01-08 13:28:18 +0100342 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100343 finish_permission_event(group, event, response);
Jan Karaaf6a5112019-01-08 13:28:18 +0100344 wake_up(&group->fanotify_data.access_waitq);
345 return 0;
346 }
347 spin_unlock(&group->notification_lock);
Eric Parisb2d87902009-12-17 21:24:34 -0500348
Jan Karaaf6a5112019-01-08 13:28:18 +0100349 return -ENOENT;
Eric Parisb2d87902009-12-17 21:24:34 -0500350}
Eric Parisb2d87902009-12-17 21:24:34 -0500351
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300352static size_t copy_error_info_to_user(struct fanotify_event *event,
353 char __user *buf, int count)
354{
Amir Goldstein3cf984e2021-11-29 22:15:33 +0200355 struct fanotify_event_info_error info = { };
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300356 struct fanotify_error_event *fee = FANOTIFY_EE(event);
357
358 info.hdr.info_type = FAN_EVENT_INFO_TYPE_ERROR;
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300359 info.hdr.len = FANOTIFY_ERROR_INFO_LEN;
360
361 if (WARN_ON(count < info.hdr.len))
362 return -EFAULT;
363
364 info.error = fee->error;
365 info.error_count = fee->err_count;
366
367 if (copy_to_user(buf, &info, sizeof(info)))
368 return -EFAULT;
369
370 return info.hdr.len;
371}
372
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000373static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,
374 int info_type, const char *name,
375 size_t name_len,
376 char __user *buf, size_t count)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200377{
378 struct fanotify_event_info_fid info = { };
379 struct file_handle handle = { };
Jan Karaafc894c2020-03-24 16:55:37 +0100380 unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200381 size_t fh_len = fh ? fh->len : 0;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200382 size_t info_len = fanotify_fid_info_len(fh_len, name_len);
383 size_t len = info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200384
Amir Goldstein44d705b2020-03-19 17:10:22 +0200385 pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n",
386 __func__, fh_len, name_len, info_len, count);
387
Amir Goldstein44d705b2020-03-19 17:10:22 +0200388 if (WARN_ON_ONCE(len < sizeof(info) || len > count))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200389 return -EFAULT;
390
Amir Goldstein44d705b2020-03-19 17:10:22 +0200391 /*
392 * Copy event info fid header followed by variable sized file handle
393 * and optionally followed by variable sized filename.
394 */
Amir Goldstein83b7a592020-07-16 11:42:26 +0300395 switch (info_type) {
396 case FAN_EVENT_INFO_TYPE_FID:
397 case FAN_EVENT_INFO_TYPE_DFID:
398 if (WARN_ON_ONCE(name_len))
399 return -EFAULT;
400 break;
401 case FAN_EVENT_INFO_TYPE_DFID_NAME:
Amir Goldstein7326e3822021-11-29 22:15:36 +0200402 case FAN_EVENT_INFO_TYPE_OLD_DFID_NAME:
403 case FAN_EVENT_INFO_TYPE_NEW_DFID_NAME:
Amir Goldstein83b7a592020-07-16 11:42:26 +0300404 if (WARN_ON_ONCE(!name || !name_len))
405 return -EFAULT;
406 break;
407 default:
408 return -EFAULT;
409 }
410
411 info.hdr.info_type = info_type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200412 info.hdr.len = len;
Amir Goldsteind766b552020-03-19 17:10:20 +0200413 info.fsid = *fsid;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200414 if (copy_to_user(buf, &info, sizeof(info)))
415 return -EFAULT;
416
417 buf += sizeof(info);
418 len -= sizeof(info);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200419 if (WARN_ON_ONCE(len < sizeof(handle)))
420 return -EFAULT;
421
Jan Karaafc894c2020-03-24 16:55:37 +0100422 handle.handle_type = fh->type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200423 handle.handle_bytes = fh_len;
Gabriel Krisman Bertazi936d6a32021-10-25 16:27:41 -0300424
425 /* Mangle handle_type for bad file_handle */
426 if (!fh_len)
427 handle.handle_type = FILEID_INVALID;
428
Amir Goldstein5e469c82019-01-10 19:04:35 +0200429 if (copy_to_user(buf, &handle, sizeof(handle)))
430 return -EFAULT;
431
432 buf += sizeof(handle);
433 len -= sizeof(handle);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200434 if (WARN_ON_ONCE(len < fh_len))
435 return -EFAULT;
436
Jan Karab2d22b62019-03-12 12:42:37 +0100437 /*
Amir Goldstein44d705b2020-03-19 17:10:22 +0200438 * For an inline fh and inline file name, copy through stack to exclude
439 * the copy from usercopy hardening protections.
Jan Karab2d22b62019-03-12 12:42:37 +0100440 */
Jan Karaafc894c2020-03-24 16:55:37 +0100441 fh_buf = fanotify_fh_buf(fh);
Jan Karab2d22b62019-03-12 12:42:37 +0100442 if (fh_len <= FANOTIFY_INLINE_FH_LEN) {
Jan Karaafc894c2020-03-24 16:55:37 +0100443 memcpy(bounce, fh_buf, fh_len);
444 fh_buf = bounce;
Jan Karab2d22b62019-03-12 12:42:37 +0100445 }
Jan Karaafc894c2020-03-24 16:55:37 +0100446 if (copy_to_user(buf, fh_buf, fh_len))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200447 return -EFAULT;
448
Amir Goldstein5e469c82019-01-10 19:04:35 +0200449 buf += fh_len;
450 len -= fh_len;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200451
452 if (name_len) {
453 /* Copy the filename with terminating null */
454 name_len++;
455 if (WARN_ON_ONCE(len < name_len))
456 return -EFAULT;
457
458 if (copy_to_user(buf, name, name_len))
459 return -EFAULT;
460
461 buf += name_len;
462 len -= name_len;
463 }
464
465 /* Pad with 0's */
Amir Goldstein5e469c82019-01-10 19:04:35 +0200466 WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
467 if (len > 0 && clear_user(buf, len))
468 return -EFAULT;
469
Amir Goldstein44d705b2020-03-19 17:10:22 +0200470 return info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200471}
472
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000473static int copy_pidfd_info_to_user(int pidfd,
474 char __user *buf,
475 size_t count)
476{
477 struct fanotify_event_info_pidfd info = { };
478 size_t info_len = FANOTIFY_PIDFD_INFO_HDR_LEN;
479
480 if (WARN_ON_ONCE(info_len > count))
481 return -EFAULT;
482
483 info.hdr.info_type = FAN_EVENT_INFO_TYPE_PIDFD;
484 info.hdr.len = info_len;
485 info.pidfd = pidfd;
486
487 if (copy_to_user(buf, &info, info_len))
488 return -EFAULT;
489
490 return info_len;
491}
492
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000493static int copy_info_records_to_user(struct fanotify_event *event,
494 struct fanotify_info *info,
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000495 unsigned int info_mode, int pidfd,
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000496 char __user *buf, size_t count)
497{
498 int ret, total_bytes = 0, info_type = 0;
499 unsigned int fid_mode = info_mode & FANOTIFY_FID_BITS;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000500 unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000501
502 /*
Amir Goldstein7326e3822021-11-29 22:15:36 +0200503 * Event info records order is as follows:
504 * 1. dir fid + name
505 * 2. (optional) new dir fid + new name
506 * 3. (optional) child fid
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000507 */
Gabriel Krisman Bertazi4bd5a5c2021-10-25 16:27:38 -0300508 if (fanotify_event_has_dir_fh(event)) {
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000509 info_type = info->name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME :
510 FAN_EVENT_INFO_TYPE_DFID;
Amir Goldstein7326e3822021-11-29 22:15:36 +0200511
512 /* FAN_RENAME uses special info types */
513 if (event->mask & FAN_RENAME)
514 info_type = FAN_EVENT_INFO_TYPE_OLD_DFID_NAME;
515
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000516 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
517 fanotify_info_dir_fh(info),
518 info_type,
519 fanotify_info_name(info),
520 info->name_len, buf, count);
521 if (ret < 0)
522 return ret;
523
524 buf += ret;
525 count -= ret;
526 total_bytes += ret;
527 }
528
Amir Goldstein7326e3822021-11-29 22:15:36 +0200529 /* New dir fid+name may be reported in addition to old dir fid+name */
530 if (fanotify_event_has_dir2_fh(event)) {
531 info_type = FAN_EVENT_INFO_TYPE_NEW_DFID_NAME;
532 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
533 fanotify_info_dir2_fh(info),
534 info_type,
535 fanotify_info_name2(info),
536 info->name2_len, buf, count);
537 if (ret < 0)
538 return ret;
539
540 buf += ret;
541 count -= ret;
542 total_bytes += ret;
543 }
544
Gabriel Krisman Bertazi4bd5a5c2021-10-25 16:27:38 -0300545 if (fanotify_event_has_object_fh(event)) {
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000546 const char *dot = NULL;
547 int dot_len = 0;
548
549 if (fid_mode == FAN_REPORT_FID || info_type) {
550 /*
551 * With only group flag FAN_REPORT_FID only type FID is
552 * reported. Second info record type is always FID.
553 */
554 info_type = FAN_EVENT_INFO_TYPE_FID;
555 } else if ((fid_mode & FAN_REPORT_NAME) &&
556 (event->mask & FAN_ONDIR)) {
557 /*
558 * With group flag FAN_REPORT_NAME, if name was not
559 * recorded in an event on a directory, report the name
560 * "." with info type DFID_NAME.
561 */
562 info_type = FAN_EVENT_INFO_TYPE_DFID_NAME;
563 dot = ".";
564 dot_len = 1;
565 } else if ((event->mask & ALL_FSNOTIFY_DIRENT_EVENTS) ||
566 (event->mask & FAN_ONDIR)) {
567 /*
568 * With group flag FAN_REPORT_DIR_FID, a single info
569 * record has type DFID for directory entry modification
570 * event and for event on a directory.
571 */
572 info_type = FAN_EVENT_INFO_TYPE_DFID;
573 } else {
574 /*
575 * With group flags FAN_REPORT_DIR_FID|FAN_REPORT_FID,
576 * a single info record has type FID for event on a
577 * non-directory, when there is no directory to report.
578 * For example, on FAN_DELETE_SELF event.
579 */
580 info_type = FAN_EVENT_INFO_TYPE_FID;
581 }
582
583 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
584 fanotify_event_object_fh(event),
585 info_type, dot, dot_len,
586 buf, count);
587 if (ret < 0)
588 return ret;
589
590 buf += ret;
591 count -= ret;
592 total_bytes += ret;
593 }
594
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000595 if (pidfd_mode) {
596 ret = copy_pidfd_info_to_user(pidfd, buf, count);
597 if (ret < 0)
598 return ret;
599
600 buf += ret;
601 count -= ret;
602 total_bytes += ret;
603 }
604
Gabriel Krisman Bertazi130a3c72021-10-25 16:27:42 -0300605 if (fanotify_is_error_event(event->mask)) {
606 ret = copy_error_info_to_user(event, buf, count);
607 if (ret < 0)
608 return ret;
609 buf += ret;
610 count -= ret;
611 total_bytes += ret;
612 }
613
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000614 return total_bytes;
615}
616
Eric Parisa1014f12009-12-17 21:24:26 -0500617static ssize_t copy_event_to_user(struct fsnotify_group *group,
Jan Kara7088f352020-03-24 17:04:20 +0100618 struct fanotify_event *event,
Kees Cook5b03a472018-12-04 15:44:46 -0800619 char __user *buf, size_t count)
Eric Parisa1014f12009-12-17 21:24:26 -0500620{
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200621 struct fanotify_event_metadata metadata;
Jan Kara7088f352020-03-24 17:04:20 +0100622 struct path *path = fanotify_event_path(event);
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300623 struct fanotify_info *info = fanotify_event_info(event);
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000624 unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000625 unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200626 struct file *f = NULL;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000627 int ret, pidfd = FAN_NOPIDFD, fd = FAN_NOFD;
Eric Parisa1014f12009-12-17 21:24:26 -0500628
Jan Kara7088f352020-03-24 17:04:20 +0100629 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
Eric Parisa1014f12009-12-17 21:24:26 -0500630
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300631 metadata.event_len = fanotify_event_len(info_mode, event);
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200632 metadata.metadata_len = FAN_EVENT_METADATA_LEN;
633 metadata.vers = FANOTIFY_METADATA_VERSION;
634 metadata.reserved = 0;
635 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
636 metadata.pid = pid_vnr(event->pid);
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200637 /*
638 * For an unprivileged listener, event->pid can be used to identify the
639 * events generated by the listener process itself, without disclosing
640 * the pids of other processes.
641 */
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300642 if (FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200643 task_tgid(current) != event->pid)
644 metadata.pid = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500645
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300646 /*
647 * For now, fid mode is required for an unprivileged listener and
648 * fid mode does not report fd in events. Keep this check anyway
649 * for safety in case fid mode requirement is relaxed in the future
650 * to allow unprivileged listener to get events with no fd and no fid.
651 */
652 if (!FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
653 path && path->mnt && path->dentry) {
Jan Karaafc894c2020-03-24 16:55:37 +0100654 fd = create_fd(group, path, &f);
655 if (fd < 0)
656 return fd;
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200657 }
658 metadata.fd = fd;
659
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000660 if (pidfd_mode) {
661 /*
662 * Complain if the FAN_REPORT_PIDFD and FAN_REPORT_TID mutual
663 * exclusion is ever lifted. At the time of incoporating pidfd
664 * support within fanotify, the pidfd API only supported the
665 * creation of pidfds for thread-group leaders.
666 */
667 WARN_ON_ONCE(FAN_GROUP_FLAG(group, FAN_REPORT_TID));
668
669 /*
670 * The PIDTYPE_TGID check for an event->pid is performed
671 * preemptively in an attempt to catch out cases where the event
672 * listener reads events after the event generating process has
673 * already terminated. Report FAN_NOPIDFD to the event listener
674 * in those cases, with all other pidfd creation errors being
675 * reported as FAN_EPIDFD.
676 */
677 if (metadata.pid == 0 ||
678 !pid_has_task(event->pid, PIDTYPE_TGID)) {
679 pidfd = FAN_NOPIDFD;
680 } else {
681 pidfd = pidfd_create(event->pid, 0);
682 if (pidfd < 0)
683 pidfd = FAN_EPIDFD;
684 }
685 }
686
Al Viro352e3b22012-08-19 12:30:45 -0400687 ret = -EFAULT;
Kees Cook5b03a472018-12-04 15:44:46 -0800688 /*
689 * Sanity check copy size in case get_one_event() and
Fabian Frederickc5e443c2020-05-12 20:18:36 +0200690 * event_len sizes ever get out of sync.
Kees Cook5b03a472018-12-04 15:44:46 -0800691 */
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200692 if (WARN_ON_ONCE(metadata.event_len > count))
Al Viro352e3b22012-08-19 12:30:45 -0400693 goto out_close_fd;
694
Amir Goldstein5e469c82019-01-10 19:04:35 +0200695 if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN))
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200696 goto out_close_fd;
697
Amir Goldstein44d705b2020-03-19 17:10:22 +0200698 buf += FAN_EVENT_METADATA_LEN;
699 count -= FAN_EVENT_METADATA_LEN;
700
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200701 if (fanotify_is_perm_event(event->mask))
Jan Kara7088f352020-03-24 17:04:20 +0100702 FANOTIFY_PERM(event)->fd = fd;
Eric Parisb2d87902009-12-17 21:24:34 -0500703
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000704 if (info_mode) {
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000705 ret = copy_info_records_to_user(event, info, info_mode, pidfd,
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000706 buf, count);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200707 if (ret < 0)
Matthew Bobrowskif644bc42021-06-11 13:32:06 +1000708 goto out_close_fd;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200709 }
710
Dan Carpenteree125952022-01-28 22:57:01 +0300711 if (f)
712 fd_install(fd, f);
713
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200714 return metadata.event_len;
Eric Parisb2d87902009-12-17 21:24:34 -0500715
Eric Parisb2d87902009-12-17 21:24:34 -0500716out_close_fd:
Al Viro352e3b22012-08-19 12:30:45 -0400717 if (fd != FAN_NOFD) {
718 put_unused_fd(fd);
719 fput(f);
720 }
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000721
722 if (pidfd >= 0)
723 close_fd(pidfd);
724
Eric Parisb2d87902009-12-17 21:24:34 -0500725 return ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500726}
727
728/* intofiy userspace file descriptor functions */
Al Viro076ccb72017-07-03 01:02:18 -0400729static __poll_t fanotify_poll(struct file *file, poll_table *wait)
Eric Parisa1014f12009-12-17 21:24:26 -0500730{
731 struct fsnotify_group *group = file->private_data;
Al Viro076ccb72017-07-03 01:02:18 -0400732 __poll_t ret = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500733
734 poll_wait(file, &group->notification_waitq, wait);
Jan Karac21dbe22016-10-07 16:56:52 -0700735 spin_lock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500736 if (!fsnotify_notify_queue_is_empty(group))
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800737 ret = EPOLLIN | EPOLLRDNORM;
Jan Karac21dbe22016-10-07 16:56:52 -0700738 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500739
740 return ret;
741}
742
743static ssize_t fanotify_read(struct file *file, char __user *buf,
744 size_t count, loff_t *pos)
745{
746 struct fsnotify_group *group;
Jan Kara7088f352020-03-24 17:04:20 +0100747 struct fanotify_event *event;
Eric Parisa1014f12009-12-17 21:24:26 -0500748 char __user *start;
749 int ret;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100750 DEFINE_WAIT_FUNC(wait, woken_wake_function);
Eric Parisa1014f12009-12-17 21:24:26 -0500751
752 start = buf;
753 group = file->private_data;
754
755 pr_debug("%s: group=%p\n", __func__, group);
756
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100757 add_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500758 while (1) {
Jan Kara47aaabd2020-07-15 14:06:21 +0200759 /*
760 * User can supply arbitrarily large buffer. Avoid softlockups
761 * in case there are lots of available events.
762 */
763 cond_resched();
Jan Kara7088f352020-03-24 17:04:20 +0100764 event = get_one_event(group, count);
765 if (IS_ERR(event)) {
766 ret = PTR_ERR(event);
Jan Karad8aaab42014-04-03 14:46:35 -0700767 break;
768 }
769
Jan Kara7088f352020-03-24 17:04:20 +0100770 if (!event) {
Jan Karad8aaab42014-04-03 14:46:35 -0700771 ret = -EAGAIN;
772 if (file->f_flags & O_NONBLOCK)
Eric Parisa1014f12009-12-17 21:24:26 -0500773 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700774
775 ret = -ERESTARTSYS;
776 if (signal_pending(current))
Eric Parisa1014f12009-12-17 21:24:26 -0500777 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700778
779 if (start != buf)
780 break;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100781
782 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
Eric Parisa1014f12009-12-17 21:24:26 -0500783 continue;
784 }
785
Jan Kara7088f352020-03-24 17:04:20 +0100786 ret = copy_event_to_user(group, event, buf, count);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300787 if (unlikely(ret == -EOPENSTALE)) {
788 /*
789 * We cannot report events with stale fd so drop it.
790 * Setting ret to 0 will continue the event loop and
791 * do the right thing if there are no more events to
792 * read (i.e. return bytes read, -EAGAIN or wait).
793 */
794 ret = 0;
795 }
796
Jan Karad8aaab42014-04-03 14:46:35 -0700797 /*
798 * Permission events get queued to wait for response. Other
799 * events can be destroyed now.
800 */
Jan Kara7088f352020-03-24 17:04:20 +0100801 if (!fanotify_is_perm_event(event->mask)) {
802 fsnotify_destroy_event(group, &event->fse);
Jan Karad5078162014-04-03 14:46:36 -0700803 } else {
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300804 if (ret <= 0) {
Jan Kara40873282019-01-08 14:02:44 +0100805 spin_lock(&group->notification_lock);
806 finish_permission_event(group,
Jan Kara7088f352020-03-24 17:04:20 +0100807 FANOTIFY_PERM(event), FAN_DENY);
Jan Karad5078162014-04-03 14:46:36 -0700808 wake_up(&group->fanotify_data.access_waitq);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300809 } else {
810 spin_lock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100811 list_add_tail(&event->fse.list,
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300812 &group->fanotify_data.access_list);
813 spin_unlock(&group->notification_lock);
Jan Karad5078162014-04-03 14:46:36 -0700814 }
Jan Karad5078162014-04-03 14:46:36 -0700815 }
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300816 if (ret < 0)
817 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700818 buf += ret;
819 count -= ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500820 }
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100821 remove_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500822
Eric Parisa1014f12009-12-17 21:24:26 -0500823 if (start != buf && ret != -EFAULT)
824 ret = buf - start;
825 return ret;
826}
827
Eric Parisb2d87902009-12-17 21:24:34 -0500828static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
829{
Eric Parisb2d87902009-12-17 21:24:34 -0500830 struct fanotify_response response = { .fd = -1, .response = -1 };
831 struct fsnotify_group *group;
832 int ret;
833
Miklos Szeredi6685df32017-10-30 21:14:56 +0100834 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
835 return -EINVAL;
836
Eric Parisb2d87902009-12-17 21:24:34 -0500837 group = file->private_data;
838
Fabian Frederick5e236632020-05-12 20:19:21 +0200839 if (count < sizeof(response))
840 return -EINVAL;
841
842 count = sizeof(response);
Eric Parisb2d87902009-12-17 21:24:34 -0500843
844 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
845
846 if (copy_from_user(&response, buf, count))
847 return -EFAULT;
848
849 ret = process_access_response(group, &response);
850 if (ret < 0)
851 count = ret;
852
853 return count;
Eric Parisb2d87902009-12-17 21:24:34 -0500854}
855
Eric Paris52c923d2009-12-17 21:24:26 -0500856static int fanotify_release(struct inode *ignored, struct file *file)
857{
858 struct fsnotify_group *group = file->private_data;
Amir Goldstein6f731712021-03-04 12:48:22 +0200859 struct fsnotify_event *fsn_event;
Andrew Morton19ba54f2010-10-28 17:21:59 -0400860
Jan Kara5838d442014-08-06 16:03:28 -0700861 /*
Jan Kara96d41012016-09-19 14:44:30 -0700862 * Stop new events from arriving in the notification queue. since
863 * userspace cannot use fanotify fd anymore, no event can enter or
864 * leave access_list by now either.
865 */
866 fsnotify_group_stop_queueing(group);
867
868 /*
869 * Process all permission events on access_list and notification queue
870 * and simulate reply from userspace.
Jan Kara5838d442014-08-06 16:03:28 -0700871 */
Jan Kara073f6552016-10-07 16:56:55 -0700872 spin_lock(&group->notification_lock);
Jan Karaca6f8692019-01-09 13:21:01 +0100873 while (!list_empty(&group->fanotify_data.access_list)) {
Jan Kara7088f352020-03-24 17:04:20 +0100874 struct fanotify_perm_event *event;
875
Jan Karaca6f8692019-01-09 13:21:01 +0100876 event = list_first_entry(&group->fanotify_data.access_list,
877 struct fanotify_perm_event, fae.fse.list);
Jan Karaf0834412014-04-03 14:46:33 -0700878 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100879 finish_permission_event(group, event, FAN_ALLOW);
880 spin_lock(&group->notification_lock);
Eric Paris2eebf582010-08-18 12:25:50 -0400881 }
Eric Paris2eebf582010-08-18 12:25:50 -0400882
Jan Kara5838d442014-08-06 16:03:28 -0700883 /*
Jan Kara96d41012016-09-19 14:44:30 -0700884 * Destroy all non-permission events. For permission events just
885 * dequeue them and set the response. They will be freed once the
886 * response is consumed and fanotify_get_response() returns.
Jan Kara5838d442014-08-06 16:03:28 -0700887 */
Amir Goldstein6f731712021-03-04 12:48:22 +0200888 while ((fsn_event = fsnotify_remove_first_event(group))) {
889 struct fanotify_event *event = FANOTIFY_E(fsn_event);
Jan Kara7088f352020-03-24 17:04:20 +0100890
Jan Kara7088f352020-03-24 17:04:20 +0100891 if (!(event->mask & FANOTIFY_PERM_EVENTS)) {
Jan Karac21dbe22016-10-07 16:56:52 -0700892 spin_unlock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200893 fsnotify_destroy_event(group, fsn_event);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100894 } else {
Jan Kara7088f352020-03-24 17:04:20 +0100895 finish_permission_event(group, FANOTIFY_PERM(event),
Jan Kara40873282019-01-08 14:02:44 +0100896 FAN_ALLOW);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100897 }
Jan Kara40873282019-01-08 14:02:44 +0100898 spin_lock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700899 }
Jan Karac21dbe22016-10-07 16:56:52 -0700900 spin_unlock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700901
902 /* Response for all permission events it set, wakeup waiters */
Eric Paris2eebf582010-08-18 12:25:50 -0400903 wake_up(&group->fanotify_data.access_waitq);
Eric Paris0a6b6bd2011-10-14 17:43:39 -0400904
Eric Paris52c923d2009-12-17 21:24:26 -0500905 /* matches the fanotify_init->fsnotify_alloc_group */
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200906 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -0500907
908 return 0;
909}
910
Eric Parisa1014f12009-12-17 21:24:26 -0500911static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
912{
913 struct fsnotify_group *group;
Jan Kara7053aee2014-01-21 15:48:14 -0800914 struct fsnotify_event *fsn_event;
Eric Parisa1014f12009-12-17 21:24:26 -0500915 void __user *p;
916 int ret = -ENOTTY;
917 size_t send_len = 0;
918
919 group = file->private_data;
920
921 p = (void __user *) arg;
922
923 switch (cmd) {
924 case FIONREAD:
Jan Karac21dbe22016-10-07 16:56:52 -0700925 spin_lock(&group->notification_lock);
Jan Kara7053aee2014-01-21 15:48:14 -0800926 list_for_each_entry(fsn_event, &group->notification_list, list)
Eric Parisa1014f12009-12-17 21:24:26 -0500927 send_len += FAN_EVENT_METADATA_LEN;
Jan Karac21dbe22016-10-07 16:56:52 -0700928 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500929 ret = put_user(send_len, (int __user *) p);
930 break;
931 }
932
933 return ret;
934}
935
Eric Paris52c923d2009-12-17 21:24:26 -0500936static const struct file_operations fanotify_fops = {
Cyrill Gorcunovbe771962012-12-17 16:05:12 -0800937 .show_fdinfo = fanotify_show_fdinfo,
Eric Parisa1014f12009-12-17 21:24:26 -0500938 .poll = fanotify_poll,
939 .read = fanotify_read,
Eric Parisb2d87902009-12-17 21:24:34 -0500940 .write = fanotify_write,
Eric Paris52c923d2009-12-17 21:24:26 -0500941 .fasync = NULL,
942 .release = fanotify_release,
Eric Parisa1014f12009-12-17 21:24:26 -0500943 .unlocked_ioctl = fanotify_ioctl,
Arnd Bergmann1832f2d2018-09-11 21:59:08 +0200944 .compat_ioctl = compat_ptr_ioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200945 .llseek = noop_llseek,
Eric Paris52c923d2009-12-17 21:24:26 -0500946};
947
Eric Paris2a3edf82009-12-17 21:24:26 -0500948static int fanotify_find_path(int dfd, const char __user *filename,
Aaron Goidelac5656d2019-08-12 11:20:00 -0400949 struct path *path, unsigned int flags, __u64 mask,
950 unsigned int obj_type)
Eric Paris2a3edf82009-12-17 21:24:26 -0500951{
952 int ret;
953
954 pr_debug("%s: dfd=%d filename=%p flags=%x\n", __func__,
955 dfd, filename, flags);
956
957 if (filename == NULL) {
Al Viro2903ff02012-08-28 12:52:22 -0400958 struct fd f = fdget(dfd);
Eric Paris2a3edf82009-12-17 21:24:26 -0500959
960 ret = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -0400961 if (!f.file)
Eric Paris2a3edf82009-12-17 21:24:26 -0500962 goto out;
963
964 ret = -ENOTDIR;
965 if ((flags & FAN_MARK_ONLYDIR) &&
Al Viro496ad9a2013-01-23 17:07:38 -0500966 !(S_ISDIR(file_inode(f.file)->i_mode))) {
Al Viro2903ff02012-08-28 12:52:22 -0400967 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500968 goto out;
969 }
970
Al Viro2903ff02012-08-28 12:52:22 -0400971 *path = f.file->f_path;
Eric Paris2a3edf82009-12-17 21:24:26 -0500972 path_get(path);
Al Viro2903ff02012-08-28 12:52:22 -0400973 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500974 } else {
975 unsigned int lookup_flags = 0;
976
977 if (!(flags & FAN_MARK_DONT_FOLLOW))
978 lookup_flags |= LOOKUP_FOLLOW;
979 if (flags & FAN_MARK_ONLYDIR)
980 lookup_flags |= LOOKUP_DIRECTORY;
981
982 ret = user_path_at(dfd, filename, lookup_flags, path);
983 if (ret)
984 goto out;
985 }
986
987 /* you can only watch an inode if you have read permissions on it */
Christian Brauner02f92b32021-01-21 14:19:22 +0100988 ret = path_permission(path, MAY_READ);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400989 if (ret) {
990 path_put(path);
991 goto out;
992 }
993
994 ret = security_path_notify(path, mask, obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -0500995 if (ret)
996 path_put(path);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400997
Eric Paris2a3edf82009-12-17 21:24:26 -0500998out:
999 return ret;
1000}
1001
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001002static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001003 __u32 mask, unsigned int flags,
1004 __u32 umask, int *destroy)
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001005{
Lino Sanfilippod2c18742015-02-10 14:08:24 -08001006 __u32 oldmask = 0;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001007
Amir Goldstein4ed68142020-07-16 11:42:14 +03001008 /* umask bits cannot be removed by user */
1009 mask &= ~umask;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001010 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001011 if (!(flags & FAN_MARK_IGNORED_MASK)) {
1012 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +03001013 fsn_mark->mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001014 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +03001015 fsn_mark->ignored_mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001016 }
Amir Goldstein4ed68142020-07-16 11:42:14 +03001017 /*
1018 * We need to keep the mark around even if remaining mask cannot
1019 * result in any events (e.g. mask == FAN_ONDIR) to support incremenal
1020 * changes to the mask.
1021 * Destroy mark when only umask bits remain.
1022 */
1023 *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001024 spin_unlock(&fsn_mark->lock);
1025
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001026 return mask & oldmask;
1027}
1028
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001029static int fanotify_remove_mark(struct fsnotify_group *group,
1030 fsnotify_connp_t *connp, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001031 unsigned int flags, __u32 umask)
Eric Paris88826272009-12-17 21:24:28 -05001032{
1033 struct fsnotify_mark *fsn_mark = NULL;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -05001034 __u32 removed;
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +02001035 int destroy_mark;
Eric Paris88826272009-12-17 21:24:28 -05001036
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001037 mutex_lock(&group->mark_mutex);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001038 fsn_mark = fsnotify_find_mark(connp, group);
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001039 if (!fsn_mark) {
1040 mutex_unlock(&group->mark_mutex);
Eric Paris88826272009-12-17 21:24:28 -05001041 return -ENOENT;
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001042 }
Eric Paris88826272009-12-17 21:24:28 -05001043
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +02001044 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001045 umask, &destroy_mark);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +03001046 if (removed & fsnotify_conn_mask(fsn_mark->connector))
1047 fsnotify_recalc_mask(fsn_mark->connector);
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +02001048 if (destroy_mark)
Jan Kara4712e7222015-09-04 15:43:12 -07001049 fsnotify_detach_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001050 mutex_unlock(&group->mark_mutex);
Jan Kara4712e7222015-09-04 15:43:12 -07001051 if (destroy_mark)
1052 fsnotify_free_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001053
Jan Karab1362ed2016-12-21 16:28:45 +01001054 /* matches the fsnotify_find_mark() */
Eric Paris2a3edf82009-12-17 21:24:26 -05001055 fsnotify_put_mark(fsn_mark);
Eric Paris2a3edf82009-12-17 21:24:26 -05001056 return 0;
1057}
1058
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001059static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
1060 struct vfsmount *mnt, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001061 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001062{
1063 return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001064 mask, flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001065}
1066
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001067static int fanotify_remove_sb_mark(struct fsnotify_group *group,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001068 struct super_block *sb, __u32 mask,
1069 unsigned int flags, __u32 umask)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001070{
Amir Goldstein4ed68142020-07-16 11:42:14 +03001071 return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
1072 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001073}
1074
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001075static int fanotify_remove_inode_mark(struct fsnotify_group *group,
1076 struct inode *inode, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001077 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001078{
1079 return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +03001080 flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001081}
1082
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001083static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
1084 __u32 mask,
1085 unsigned int flags)
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001086{
Eric Paris192ca4d2010-10-28 17:21:59 -04001087 __u32 oldmask = -1;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001088
1089 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001090 if (!(flags & FAN_MARK_IGNORED_MASK)) {
1091 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +03001092 fsn_mark->mask |= mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001093 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +03001094 fsn_mark->ignored_mask |= mask;
Eric Parisc9778a92009-12-17 21:24:33 -05001095 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
1096 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001097 }
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001098 spin_unlock(&fsn_mark->lock);
1099
1100 return mask & ~oldmask;
1101}
1102
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001103static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
Amir Goldsteinb812a9f2018-06-23 17:54:48 +03001104 fsnotify_connp_t *connp,
Amir Goldsteinad69cd92021-11-29 22:15:27 +02001105 unsigned int obj_type,
Amir Goldstein77115222019-01-10 19:04:37 +02001106 __kernel_fsid_t *fsid)
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001107{
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001108 struct ucounts *ucounts = group->fanotify_data.ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001109 struct fsnotify_mark *mark;
1110 int ret;
1111
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001112 /*
1113 * Enforce per user marks limits per user in all containing user ns.
1114 * A group with FAN_UNLIMITED_MARKS does not contribute to mark count
1115 * in the limited groups account.
1116 */
1117 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS) &&
1118 !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001119 return ERR_PTR(-ENOSPC);
1120
1121 mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001122 if (!mark) {
1123 ret = -ENOMEM;
1124 goto out_dec_ucounts;
1125 }
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001126
Jan Kara054c6362016-12-21 18:06:12 +01001127 fsnotify_init_mark(mark, group);
Amir Goldsteinad69cd92021-11-29 22:15:27 +02001128 ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001129 if (ret) {
1130 fsnotify_put_mark(mark);
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001131 goto out_dec_ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001132 }
1133
1134 return mark;
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001135
1136out_dec_ucounts:
1137 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
1138 dec_ucount(ucounts, UCOUNT_FANOTIFY_MARKS);
1139 return ERR_PTR(ret);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001140}
1141
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -03001142static int fanotify_group_init_error_pool(struct fsnotify_group *group)
1143{
1144 if (mempool_initialized(&group->fanotify_data.error_events_pool))
1145 return 0;
1146
1147 return mempool_init_kmalloc_pool(&group->fanotify_data.error_events_pool,
1148 FANOTIFY_DEFAULT_FEE_POOL_SIZE,
1149 sizeof(struct fanotify_error_event));
1150}
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001151
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001152static int fanotify_add_mark(struct fsnotify_group *group,
Amir Goldsteinad69cd92021-11-29 22:15:27 +02001153 fsnotify_connp_t *connp, unsigned int obj_type,
Amir Goldstein77115222019-01-10 19:04:37 +02001154 __u32 mask, unsigned int flags,
1155 __kernel_fsid_t *fsid)
Eric Paris2a3edf82009-12-17 21:24:26 -05001156{
1157 struct fsnotify_mark *fsn_mark;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001158 __u32 added;
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -03001159 int ret = 0;
Eric Paris2a3edf82009-12-17 21:24:26 -05001160
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001161 mutex_lock(&group->mark_mutex);
Amir Goldsteinb812a9f2018-06-23 17:54:48 +03001162 fsn_mark = fsnotify_find_mark(connp, group);
Eric Paris88826272009-12-17 21:24:28 -05001163 if (!fsn_mark) {
Amir Goldsteinad69cd92021-11-29 22:15:27 +02001164 fsn_mark = fanotify_add_new_mark(group, connp, obj_type, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001165 if (IS_ERR(fsn_mark)) {
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001166 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001167 return PTR_ERR(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001168 }
Eric Paris88826272009-12-17 21:24:28 -05001169 }
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -03001170
1171 /*
1172 * Error events are pre-allocated per group, only if strictly
1173 * needed (i.e. FAN_FS_ERROR was requested).
1174 */
1175 if (!(flags & FAN_MARK_IGNORED_MASK) && (mask & FAN_FS_ERROR)) {
1176 ret = fanotify_group_init_error_pool(group);
1177 if (ret)
1178 goto out;
1179 }
1180
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001181 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +03001182 if (added & ~fsnotify_conn_mask(fsn_mark->connector))
1183 fsnotify_recalc_mask(fsn_mark->connector);
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -03001184
1185out:
Jan Karac9747642016-12-14 13:53:46 +01001186 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001187
Lino Sanfilippofa218ab2010-11-09 18:18:16 +01001188 fsnotify_put_mark(fsn_mark);
Gabriel Krisman Bertazi734a1a52021-10-25 16:27:34 -03001189 return ret;
Eric Paris88826272009-12-17 21:24:28 -05001190}
1191
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001192static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
1193 struct vfsmount *mnt, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +02001194 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001195{
1196 return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001197 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001198}
1199
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001200static int fanotify_add_sb_mark(struct fsnotify_group *group,
Amir Goldstein77115222019-01-10 19:04:37 +02001201 struct super_block *sb, __u32 mask,
1202 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001203{
1204 return fanotify_add_mark(group, &sb->s_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001205 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001206}
1207
Andreas Gruenbacher52202df2009-12-17 21:24:28 -05001208static int fanotify_add_inode_mark(struct fsnotify_group *group,
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001209 struct inode *inode, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +02001210 unsigned int flags, __kernel_fsid_t *fsid)
Eric Paris88826272009-12-17 21:24:28 -05001211{
Eric Paris88826272009-12-17 21:24:28 -05001212 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
Eric Paris2a3edf82009-12-17 21:24:26 -05001213
Eric Paris5322a592010-10-28 17:21:57 -04001214 /*
1215 * If some other task has this inode open for write we should not add
1216 * an ignored mark, unless that ignored mark is supposed to survive
1217 * modification changes anyway.
1218 */
1219 if ((flags & FAN_MARK_IGNORED_MASK) &&
1220 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
Nikolay Borisovac9498d2018-12-11 10:27:23 +02001221 inode_is_open_for_write(inode))
Eric Paris5322a592010-10-28 17:21:57 -04001222 return 0;
1223
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001224 return fanotify_add_mark(group, &inode->i_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001225 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
Eric Paris88826272009-12-17 21:24:28 -05001226}
Eric Paris2a3edf82009-12-17 21:24:26 -05001227
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001228static struct fsnotify_event *fanotify_alloc_overflow_event(void)
1229{
1230 struct fanotify_event *oevent;
1231
1232 oevent = kmalloc(sizeof(*oevent), GFP_KERNEL_ACCOUNT);
1233 if (!oevent)
1234 return NULL;
1235
1236 fanotify_init_event(oevent, 0, FS_Q_OVERFLOW);
1237 oevent->type = FANOTIFY_EVENT_TYPE_OVERFLOW;
1238
1239 return &oevent->fse;
1240}
1241
Amir Goldstein94e00d22021-03-04 12:48:25 +02001242static struct hlist_head *fanotify_alloc_merge_hash(void)
1243{
1244 struct hlist_head *hash;
1245
1246 hash = kmalloc(sizeof(struct hlist_head) << FANOTIFY_HTABLE_BITS,
1247 GFP_KERNEL_ACCOUNT);
1248 if (!hash)
1249 return NULL;
1250
1251 __hash_init(hash, FANOTIFY_HTABLE_SIZE);
1252
1253 return hash;
1254}
1255
Eric Paris52c923d2009-12-17 21:24:26 -05001256/* fanotify syscalls */
Eric Paris08ae8932010-05-27 09:41:40 -04001257SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
Eric Paris11637e42009-12-17 21:24:25 -05001258{
Eric Paris52c923d2009-12-17 21:24:26 -05001259 struct fsnotify_group *group;
1260 int f_flags, fd;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001261 unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
1262 unsigned int class = flags & FANOTIFY_CLASS_BITS;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001263 unsigned int internal_flags = 0;
Eric Paris52c923d2009-12-17 21:24:26 -05001264
Amir Goldstein96a71f22018-09-21 21:20:30 +03001265 pr_debug("%s: flags=%x event_f_flags=%x\n",
1266 __func__, flags, event_f_flags);
Eric Paris52c923d2009-12-17 21:24:26 -05001267
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001268 if (!capable(CAP_SYS_ADMIN)) {
1269 /*
1270 * An unprivileged user can setup an fanotify group with
1271 * limited functionality - an unprivileged group is limited to
1272 * notification events with file handles and it cannot use
1273 * unlimited queue/marks.
1274 */
1275 if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode)
1276 return -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001277
1278 /*
1279 * Setting the internal flag FANOTIFY_UNPRIV on the group
1280 * prevents setting mount/filesystem marks on this group and
1281 * prevents reporting pid and open fd in events.
1282 */
1283 internal_flags |= FANOTIFY_UNPRIV;
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001284 }
Eric Paris52c923d2009-12-17 21:24:26 -05001285
Steve Grubbde8cd832017-10-02 20:21:39 -04001286#ifdef CONFIG_AUDITSYSCALL
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001287 if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -04001288#else
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001289 if (flags & ~FANOTIFY_INIT_FLAGS)
Steve Grubbde8cd832017-10-02 20:21:39 -04001290#endif
Eric Paris52c923d2009-12-17 21:24:26 -05001291 return -EINVAL;
1292
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +10001293 /*
1294 * A pidfd can only be returned for a thread-group leader; thus
1295 * FAN_REPORT_PIDFD and FAN_REPORT_TID need to remain mutually
1296 * exclusive.
1297 */
1298 if ((flags & FAN_REPORT_PIDFD) && (flags & FAN_REPORT_TID))
1299 return -EINVAL;
1300
Heinrich Schuchardt48149e92014-06-04 16:05:44 -07001301 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
1302 return -EINVAL;
1303
1304 switch (event_f_flags & O_ACCMODE) {
1305 case O_RDONLY:
1306 case O_RDWR:
1307 case O_WRONLY:
1308 break;
1309 default:
1310 return -EINVAL;
1311 }
1312
Amir Goldstein83b7a592020-07-16 11:42:26 +03001313 if (fid_mode && class != FAN_CLASS_NOTIF)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001314 return -EINVAL;
1315
Amir Goldstein929943b2020-07-16 11:42:28 +03001316 /*
Amir Goldstein929943b2020-07-16 11:42:28 +03001317 * Child name is reported with parent fid so requires dir fid.
Amir Goldstein691d9762020-07-16 11:42:30 +03001318 * We can report both child fid and dir fid with or without name.
Amir Goldstein929943b2020-07-16 11:42:28 +03001319 */
Amir Goldstein691d9762020-07-16 11:42:30 +03001320 if ((fid_mode & FAN_REPORT_NAME) && !(fid_mode & FAN_REPORT_DIR_FID))
Amir Goldstein83b7a592020-07-16 11:42:26 +03001321 return -EINVAL;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001322
Amir Goldsteind61fd652021-11-29 22:15:29 +02001323 /*
1324 * FAN_REPORT_TARGET_FID requires FAN_REPORT_NAME and FAN_REPORT_FID
1325 * and is used as an indication to report both dir and child fid on all
1326 * dirent events.
1327 */
1328 if ((fid_mode & FAN_REPORT_TARGET_FID) &&
1329 (!(fid_mode & FAN_REPORT_NAME) || !(fid_mode & FAN_REPORT_FID)))
1330 return -EINVAL;
1331
Eric Parisb2d87902009-12-17 21:24:34 -05001332 f_flags = O_RDWR | FMODE_NONOTIFY;
Eric Paris52c923d2009-12-17 21:24:26 -05001333 if (flags & FAN_CLOEXEC)
1334 f_flags |= O_CLOEXEC;
1335 if (flags & FAN_NONBLOCK)
1336 f_flags |= O_NONBLOCK;
1337
1338 /* fsnotify_alloc_group takes a ref. Dropped in fanotify_release */
Shakeel Buttac7b79f2020-12-19 20:46:08 -08001339 group = fsnotify_alloc_user_group(&fanotify_fsnotify_ops);
Eric Paris26379192010-11-23 23:48:26 -05001340 if (IS_ERR(group)) {
Eric Paris52c923d2009-12-17 21:24:26 -05001341 return PTR_ERR(group);
Eric Paris26379192010-11-23 23:48:26 -05001342 }
Eric Paris52c923d2009-12-17 21:24:26 -05001343
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001344 /* Enforce groups limits per user in all containing user ns */
1345 group->fanotify_data.ucounts = inc_ucount(current_user_ns(),
1346 current_euid(),
1347 UCOUNT_FANOTIFY_GROUPS);
1348 if (!group->fanotify_data.ucounts) {
1349 fd = -EMFILE;
1350 goto out_destroy_group;
1351 }
1352
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001353 group->fanotify_data.flags = flags | internal_flags;
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001354 group->memcg = get_mem_cgroup_from_mm(current->mm);
Eric Paris4afeff82010-10-28 17:21:58 -04001355
Amir Goldstein94e00d22021-03-04 12:48:25 +02001356 group->fanotify_data.merge_hash = fanotify_alloc_merge_hash();
1357 if (!group->fanotify_data.merge_hash) {
1358 fd = -ENOMEM;
1359 goto out_destroy_group;
1360 }
1361
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001362 group->overflow_event = fanotify_alloc_overflow_event();
1363 if (unlikely(!group->overflow_event)) {
Jan Karaff57cd52014-02-21 19:14:11 +01001364 fd = -ENOMEM;
1365 goto out_destroy_group;
1366 }
Jan Karaff57cd52014-02-21 19:14:11 +01001367
Will Woods1e2ee492014-05-06 12:50:10 -07001368 if (force_o_largefile())
1369 event_f_flags |= O_LARGEFILE;
Eric Paris80af2582010-07-28 10:18:37 -04001370 group->fanotify_data.f_flags = event_f_flags;
Eric Paris9e66e422009-12-17 21:24:34 -05001371 init_waitqueue_head(&group->fanotify_data.access_waitq);
1372 INIT_LIST_HEAD(&group->fanotify_data.access_list);
Amir Goldstein83b7a592020-07-16 11:42:26 +03001373 switch (class) {
Eric Paris4231a232010-10-28 17:21:56 -04001374 case FAN_CLASS_NOTIF:
1375 group->priority = FS_PRIO_0;
1376 break;
1377 case FAN_CLASS_CONTENT:
1378 group->priority = FS_PRIO_1;
1379 break;
1380 case FAN_CLASS_PRE_CONTENT:
1381 group->priority = FS_PRIO_2;
1382 break;
1383 default:
1384 fd = -EINVAL;
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001385 goto out_destroy_group;
Eric Paris4231a232010-10-28 17:21:56 -04001386 }
Eric Pariscb2d4292009-12-17 21:24:34 -05001387
Eric Paris5dd03f52010-10-28 17:21:57 -04001388 if (flags & FAN_UNLIMITED_QUEUE) {
1389 fd = -EPERM;
1390 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001391 goto out_destroy_group;
Eric Paris5dd03f52010-10-28 17:21:57 -04001392 group->max_events = UINT_MAX;
1393 } else {
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001394 group->max_events = fanotify_max_queued_events;
Eric Paris5dd03f52010-10-28 17:21:57 -04001395 }
Eric Paris2529a0d2010-10-28 17:21:57 -04001396
Eric Parisac7e22d2010-10-28 17:21:58 -04001397 if (flags & FAN_UNLIMITED_MARKS) {
1398 fd = -EPERM;
1399 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001400 goto out_destroy_group;
Eric Parisac7e22d2010-10-28 17:21:58 -04001401 }
Eric Parise7099d82010-10-28 17:21:57 -04001402
Steve Grubbde8cd832017-10-02 20:21:39 -04001403 if (flags & FAN_ENABLE_AUDIT) {
1404 fd = -EPERM;
1405 if (!capable(CAP_AUDIT_WRITE))
1406 goto out_destroy_group;
Steve Grubbde8cd832017-10-02 20:21:39 -04001407 }
1408
Eric Paris52c923d2009-12-17 21:24:26 -05001409 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
1410 if (fd < 0)
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001411 goto out_destroy_group;
Eric Paris52c923d2009-12-17 21:24:26 -05001412
1413 return fd;
1414
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001415out_destroy_group:
1416 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -05001417 return fd;
Eric Paris11637e42009-12-17 21:24:25 -05001418}
Eric Parisbbaa4162009-12-17 21:24:26 -05001419
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001420static int fanotify_test_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001421{
Amir Goldstein73072282019-01-10 19:04:39 +02001422 __kernel_fsid_t root_fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001423 int err;
1424
1425 /*
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001426 * Make sure dentry is not of a filesystem with zero fsid (e.g. fuse).
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001427 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001428 err = vfs_get_fsid(dentry, fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001429 if (err)
1430 return err;
1431
Amir Goldstein73072282019-01-10 19:04:39 +02001432 if (!fsid->val[0] && !fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001433 return -ENODEV;
1434
1435 /*
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001436 * Make sure dentry is not of a filesystem subvolume (e.g. btrfs)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001437 * which uses a different fsid than sb root.
1438 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001439 err = vfs_get_fsid(dentry->d_sb->s_root, &root_fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001440 if (err)
1441 return err;
1442
Amir Goldstein73072282019-01-10 19:04:39 +02001443 if (root_fsid.val[0] != fsid->val[0] ||
1444 root_fsid.val[1] != fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001445 return -EXDEV;
1446
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001447 return 0;
1448}
1449
1450/* Check if filesystem can encode a unique fid */
1451static int fanotify_test_fid(struct dentry *dentry)
1452{
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001453 /*
1454 * We need to make sure that the file system supports at least
1455 * encoding a file handle so user can use name_to_handle_at() to
1456 * compare fid returned with event to the file handle of watched
1457 * objects. However, name_to_handle_at() requires that the
1458 * filesystem also supports decoding file handles.
1459 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001460 if (!dentry->d_sb->s_export_op ||
1461 !dentry->d_sb->s_export_op->fh_to_dentry)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001462 return -EOPNOTSUPP;
1463
1464 return 0;
1465}
1466
Jan Kara0b3b0942019-05-15 16:28:34 +02001467static int fanotify_events_supported(struct path *path, __u64 mask)
1468{
1469 /*
1470 * Some filesystems such as 'proc' acquire unusual locks when opening
1471 * files. For them fanotify permission events have high chances of
1472 * deadlocking the system - open done when reporting fanotify event
1473 * blocks on this "unusual" lock while another process holding the lock
1474 * waits for fanotify permission event to be answered. Just disallow
1475 * permission events for such filesystems.
1476 */
1477 if (mask & FANOTIFY_PERM_EVENTS &&
1478 path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
1479 return -EINVAL;
1480 return 0;
1481}
1482
Dominik Brodowski183caa32018-03-17 15:06:11 +01001483static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1484 int dfd, const char __user *pathname)
Eric Parisbbaa4162009-12-17 21:24:26 -05001485{
Eric Paris0ff21db2009-12-17 21:24:29 -05001486 struct inode *inode = NULL;
1487 struct vfsmount *mnt = NULL;
Eric Paris2a3edf82009-12-17 21:24:26 -05001488 struct fsnotify_group *group;
Al Viro2903ff02012-08-28 12:52:22 -04001489 struct fd f;
Eric Paris2a3edf82009-12-17 21:24:26 -05001490 struct path path;
Amir Goldstein73072282019-01-10 19:04:39 +02001491 __kernel_fsid_t __fsid, *fsid = NULL;
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001492 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001493 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
Amir Goldstein3ef86652020-07-16 11:42:13 +03001494 bool ignored = flags & FAN_MARK_IGNORED_MASK;
Amir Goldsteind809daf2020-07-16 11:42:12 +03001495 unsigned int obj_type, fid_mode;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001496 u32 umask = 0;
Al Viro2903ff02012-08-28 12:52:22 -04001497 int ret;
Eric Paris2a3edf82009-12-17 21:24:26 -05001498
1499 pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
1500 __func__, fanotify_fd, flags, dfd, pathname, mask);
1501
1502 /* we only use the lower 32 bits as of right now. */
Christian Brauner22d483b2021-03-25 09:37:43 +01001503 if (upper_32_bits(mask))
Eric Paris2a3edf82009-12-17 21:24:26 -05001504 return -EINVAL;
1505
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001506 if (flags & ~FANOTIFY_MARK_FLAGS)
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001507 return -EINVAL;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001508
1509 switch (mark_type) {
1510 case FAN_MARK_INODE:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001511 obj_type = FSNOTIFY_OBJ_TYPE_INODE;
1512 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001513 case FAN_MARK_MOUNT:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001514 obj_type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
1515 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001516 case FAN_MARK_FILESYSTEM:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001517 obj_type = FSNOTIFY_OBJ_TYPE_SB;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001518 break;
1519 default:
1520 return -EINVAL;
1521 }
1522
Eric Paris4d926042009-12-17 21:24:34 -05001523 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001524 case FAN_MARK_ADD:
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001525 case FAN_MARK_REMOVE:
Lino Sanfilippo1734dee2010-11-22 18:46:33 +01001526 if (!mask)
1527 return -EINVAL;
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001528 break;
Eric Paris4d926042009-12-17 21:24:34 -05001529 case FAN_MARK_FLUSH:
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001530 if (flags & ~(FANOTIFY_MARK_TYPE_BITS | FAN_MARK_FLUSH))
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001531 return -EINVAL;
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001532 break;
1533 default:
1534 return -EINVAL;
1535 }
Eric Paris8fcd6522010-10-28 17:21:59 -04001536
Miklos Szeredi6685df32017-10-30 21:14:56 +01001537 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001538 valid_mask |= FANOTIFY_PERM_EVENTS;
Miklos Szeredi6685df32017-10-30 21:14:56 +01001539
1540 if (mask & ~valid_mask)
Eric Paris2a3edf82009-12-17 21:24:26 -05001541 return -EINVAL;
1542
Amir Goldstein3ef86652020-07-16 11:42:13 +03001543 /* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */
1544 if (ignored)
1545 mask &= ~FANOTIFY_EVENT_FLAGS;
1546
Al Viro2903ff02012-08-28 12:52:22 -04001547 f = fdget(fanotify_fd);
1548 if (unlikely(!f.file))
Eric Paris2a3edf82009-12-17 21:24:26 -05001549 return -EBADF;
1550
1551 /* verify that this is indeed an fanotify instance */
1552 ret = -EINVAL;
Al Viro2903ff02012-08-28 12:52:22 -04001553 if (unlikely(f.file->f_op != &fanotify_fops))
Eric Paris2a3edf82009-12-17 21:24:26 -05001554 goto fput_and_out;
Al Viro2903ff02012-08-28 12:52:22 -04001555 group = f.file->private_data;
Eric Paris4231a232010-10-28 17:21:56 -04001556
1557 /*
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001558 * An unprivileged user is not allowed to setup mount nor filesystem
1559 * marks. This also includes setting up such marks by a group that
1560 * was initialized by an unprivileged user.
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001561 */
1562 ret = -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001563 if ((!capable(CAP_SYS_ADMIN) ||
1564 FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001565 mark_type != FAN_MARK_INODE)
1566 goto fput_and_out;
1567
1568 /*
Eric Paris4231a232010-10-28 17:21:56 -04001569 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
1570 * allowed to set permissions events.
1571 */
1572 ret = -EINVAL;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001573 if (mask & FANOTIFY_PERM_EVENTS &&
Eric Paris4231a232010-10-28 17:21:56 -04001574 group->priority == FS_PRIO_0)
1575 goto fput_and_out;
Eric Paris2a3edf82009-12-17 21:24:26 -05001576
Gabriel Krisman Bertazi9709bd52021-10-25 16:27:43 -03001577 if (mask & FAN_FS_ERROR &&
1578 mark_type != FAN_MARK_FILESYSTEM)
1579 goto fput_and_out;
1580
Amir Goldstein235328d2019-01-10 19:04:43 +02001581 /*
Gabriel Krisman Bertazi4fe595c2021-10-25 16:27:31 -03001582 * Events that do not carry enough information to report
1583 * event->fd require a group that supports reporting fid. Those
1584 * events are not supported on a mount mark, because they do not
1585 * carry enough information (i.e. path) to be filtered by mount
1586 * point.
Amir Goldstein235328d2019-01-10 19:04:43 +02001587 */
Amir Goldsteind809daf2020-07-16 11:42:12 +03001588 fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
Gabriel Krisman Bertazi4fe595c2021-10-25 16:27:31 -03001589 if (mask & ~(FANOTIFY_FD_EVENTS|FANOTIFY_EVENT_FLAGS) &&
Amir Goldsteind809daf2020-07-16 11:42:12 +03001590 (!fid_mode || mark_type == FAN_MARK_MOUNT))
Amir Goldstein235328d2019-01-10 19:04:43 +02001591 goto fput_and_out;
1592
Amir Goldstein8cc3b1c2021-11-29 22:15:37 +02001593 /*
1594 * FAN_RENAME uses special info type records to report the old and
1595 * new parent+name. Reporting only old and new parent id is less
1596 * useful and was not implemented.
1597 */
1598 if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME))
1599 goto fput_and_out;
1600
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001601 if (flags & FAN_MARK_FLUSH) {
1602 ret = 0;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001603 if (mark_type == FAN_MARK_MOUNT)
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001604 fsnotify_clear_vfsmount_marks_by_group(group);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001605 else if (mark_type == FAN_MARK_FILESYSTEM)
1606 fsnotify_clear_sb_marks_by_group(group);
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001607 else
1608 fsnotify_clear_inode_marks_by_group(group);
1609 goto fput_and_out;
1610 }
1611
Aaron Goidelac5656d2019-08-12 11:20:00 -04001612 ret = fanotify_find_path(dfd, pathname, &path, flags,
1613 (mask & ALL_FSNOTIFY_EVENTS), obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -05001614 if (ret)
1615 goto fput_and_out;
1616
Jan Kara0b3b0942019-05-15 16:28:34 +02001617 if (flags & FAN_MARK_ADD) {
1618 ret = fanotify_events_supported(&path, mask);
1619 if (ret)
1620 goto path_put_and_out;
1621 }
1622
Amir Goldsteind809daf2020-07-16 11:42:12 +03001623 if (fid_mode) {
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001624 ret = fanotify_test_fsid(path.dentry, &__fsid);
1625 if (ret)
1626 goto path_put_and_out;
1627
1628 ret = fanotify_test_fid(path.dentry);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001629 if (ret)
1630 goto path_put_and_out;
Amir Goldstein77115222019-01-10 19:04:37 +02001631
Amir Goldstein73072282019-01-10 19:04:39 +02001632 fsid = &__fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001633 }
1634
Eric Paris2a3edf82009-12-17 21:24:26 -05001635 /* inode held in place by reference to path; group by fget on fd */
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001636 if (mark_type == FAN_MARK_INODE)
Eric Paris0ff21db2009-12-17 21:24:29 -05001637 inode = path.dentry->d_inode;
1638 else
1639 mnt = path.mnt;
Eric Paris2a3edf82009-12-17 21:24:26 -05001640
Amir Goldstein85af5d92020-07-16 11:42:15 +03001641 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1642 if (mnt || !S_ISDIR(inode->i_mode)) {
1643 mask &= ~FAN_EVENT_ON_CHILD;
1644 umask = FAN_EVENT_ON_CHILD;
Amir Goldstein51280632020-07-16 11:42:27 +03001645 /*
1646 * If group needs to report parent fid, register for getting
1647 * events with parent/name info for non-directory.
1648 */
1649 if ((fid_mode & FAN_REPORT_DIR_FID) &&
1650 (flags & FAN_MARK_ADD) && !ignored)
1651 mask |= FAN_EVENT_ON_CHILD;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001652 }
1653
Eric Paris2a3edf82009-12-17 21:24:26 -05001654 /* create/update an inode mark */
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001655 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001656 case FAN_MARK_ADD:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001657 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001658 ret = fanotify_add_vfsmount_mark(group, mnt, mask,
1659 flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001660 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001661 ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
1662 flags, fsid);
Eric Paris0ff21db2009-12-17 21:24:29 -05001663 else
Amir Goldstein77115222019-01-10 19:04:37 +02001664 ret = fanotify_add_inode_mark(group, inode, mask,
1665 flags, fsid);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001666 break;
1667 case FAN_MARK_REMOVE:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001668 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001669 ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001670 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001671 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001672 ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001673 flags, umask);
Andreas Gruenbacherf3640192009-12-17 21:24:29 -05001674 else
Amir Goldstein77115222019-01-10 19:04:37 +02001675 ret = fanotify_remove_inode_mark(group, inode, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001676 flags, umask);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001677 break;
1678 default:
1679 ret = -EINVAL;
1680 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001681
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001682path_put_and_out:
Eric Paris2a3edf82009-12-17 21:24:26 -05001683 path_put(&path);
1684fput_and_out:
Al Viro2903ff02012-08-28 12:52:22 -04001685 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -05001686 return ret;
Eric Parisbbaa4162009-12-17 21:24:26 -05001687}
Eric Paris2a3edf82009-12-17 21:24:26 -05001688
Brian Gerst2ca408d2020-11-30 17:30:59 -05001689#ifndef CONFIG_ARCH_SPLIT_ARG64
Dominik Brodowski183caa32018-03-17 15:06:11 +01001690SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags,
1691 __u64, mask, int, dfd,
1692 const char __user *, pathname)
1693{
1694 return do_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
1695}
Brian Gerst2ca408d2020-11-30 17:30:59 -05001696#endif
Dominik Brodowski183caa32018-03-17 15:06:11 +01001697
Brian Gerst2ca408d2020-11-30 17:30:59 -05001698#if defined(CONFIG_ARCH_SPLIT_ARG64) || defined(CONFIG_COMPAT)
1699SYSCALL32_DEFINE6(fanotify_mark,
Al Viro91c2e0b2013-03-05 20:10:59 -05001700 int, fanotify_fd, unsigned int, flags,
Brian Gerst2ca408d2020-11-30 17:30:59 -05001701 SC_ARG64(mask), int, dfd,
Al Viro91c2e0b2013-03-05 20:10:59 -05001702 const char __user *, pathname)
1703{
Brian Gerst2ca408d2020-11-30 17:30:59 -05001704 return do_fanotify_mark(fanotify_fd, flags, SC_VAL64(__u64, mask),
1705 dfd, pathname);
Al Viro91c2e0b2013-03-05 20:10:59 -05001706}
1707#endif
1708
Eric Paris2a3edf82009-12-17 21:24:26 -05001709/*
Justin P. Mattockae0e47f2011-03-01 15:06:02 +01001710 * fanotify_user_setup - Our initialization function. Note that we cannot return
Eric Paris2a3edf82009-12-17 21:24:26 -05001711 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1712 * must result in panic().
1713 */
1714static int __init fanotify_user_setup(void)
1715{
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001716 struct sysinfo si;
1717 int max_marks;
1718
1719 si_meminfo(&si);
1720 /*
1721 * Allow up to 1% of addressable memory to be accounted for per user
1722 * marks limited to the range [8192, 1048576]. mount and sb marks are
1723 * a lot cheaper than inode marks, but there is no reason for a user
1724 * to have many of those, so calculate by the cost of inode marks.
1725 */
1726 max_marks = (((si.totalram - si.totalhigh) / 100) << PAGE_SHIFT) /
1727 INODE_MARK_COST;
1728 max_marks = clamp(max_marks, FANOTIFY_OLD_DEFAULT_MAX_MARKS,
1729 FANOTIFY_DEFAULT_MAX_USER_MARKS);
1730
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001731 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
Amir Goldsteind61fd652021-11-29 22:15:29 +02001732 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 12);
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001733 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
1734
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001735 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
1736 SLAB_PANIC|SLAB_ACCOUNT);
Jan Kara7088f352020-03-24 17:04:20 +01001737 fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
1738 SLAB_PANIC);
1739 fanotify_path_event_cachep = KMEM_CACHE(fanotify_path_event,
1740 SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001741 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) {
1742 fanotify_perm_event_cachep =
Amir Goldstein33913992019-01-10 19:04:32 +02001743 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001744 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001745
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001746 fanotify_max_queued_events = FANOTIFY_DEFAULT_MAX_EVENTS;
1747 init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS] =
1748 FANOTIFY_DEFAULT_MAX_GROUPS;
1749 init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS] = max_marks;
Xiaoming Ni7b9ad122022-01-21 22:11:59 -08001750 fanotify_sysctls_init();
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001751
Eric Paris2a3edf82009-12-17 21:24:26 -05001752 return 0;
1753}
1754device_initcall(fanotify_user_setup);