blob: adeae6d65e351148679af5d0eeae170c0f6fca11 [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
33
34/*
35 * Legacy fanotify marks limits (8192) is per group and we introduced a tunable
36 * limit of marks per user, similar to inotify. Effectively, the legacy limit
37 * of fanotify marks per user is <max marks per group> * <max groups per user>.
38 * This default limit (1M) also happens to match the increased limit of inotify
39 * max_user_watches since v5.10.
40 */
41#define FANOTIFY_DEFAULT_MAX_USER_MARKS \
42 (FANOTIFY_OLD_DEFAULT_MAX_MARKS * FANOTIFY_DEFAULT_MAX_GROUPS)
43
44/*
45 * Most of the memory cost of adding an inode mark is pinning the marked inode.
46 * The size of the filesystem inode struct is not uniform across filesystems,
47 * so double the size of a VFS inode is used as a conservative approximation.
48 */
49#define INODE_MARK_COST (2 * sizeof(struct inode))
50
51/* configurable via /proc/sys/fs/fanotify/ */
52static int fanotify_max_queued_events __read_mostly;
53
54#ifdef CONFIG_SYSCTL
55
56#include <linux/sysctl.h>
57
Sven Schnellef153c222021-07-30 08:28:54 +020058static long ft_zero = 0;
59static long ft_int_max = INT_MAX;
60
Amir Goldstein5b8fea62021-03-04 13:29:20 +020061struct ctl_table fanotify_table[] = {
62 {
63 .procname = "max_user_groups",
64 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS],
Sven Schnellef153c222021-07-30 08:28:54 +020065 .maxlen = sizeof(long),
Amir Goldstein5b8fea62021-03-04 13:29:20 +020066 .mode = 0644,
Sven Schnellef153c222021-07-30 08:28:54 +020067 .proc_handler = proc_doulongvec_minmax,
68 .extra1 = &ft_zero,
69 .extra2 = &ft_int_max,
Amir Goldstein5b8fea62021-03-04 13:29:20 +020070 },
71 {
72 .procname = "max_user_marks",
73 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS],
Sven Schnellef153c222021-07-30 08:28:54 +020074 .maxlen = sizeof(long),
Amir Goldstein5b8fea62021-03-04 13:29:20 +020075 .mode = 0644,
Sven Schnellef153c222021-07-30 08:28:54 +020076 .proc_handler = proc_doulongvec_minmax,
77 .extra1 = &ft_zero,
78 .extra2 = &ft_int_max,
Amir Goldstein5b8fea62021-03-04 13:29:20 +020079 },
80 {
81 .procname = "max_queued_events",
82 .data = &fanotify_max_queued_events,
83 .maxlen = sizeof(int),
84 .mode = 0644,
85 .proc_handler = proc_dointvec_minmax,
86 .extra1 = SYSCTL_ZERO
87 },
88 { }
89};
90#endif /* CONFIG_SYSCTL */
Eric Paris2529a0d2010-10-28 17:21:57 -040091
Heinrich Schuchardt48149e92014-06-04 16:05:44 -070092/*
93 * All flags that may be specified in parameter event_f_flags of fanotify_init.
94 *
95 * Internal and external open flags are stored together in field f_flags of
96 * struct file. Only external open flags shall be allowed in event_f_flags.
97 * Internal flags like FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME shall be
98 * excluded.
99 */
100#define FANOTIFY_INIT_ALL_EVENT_F_BITS ( \
101 O_ACCMODE | O_APPEND | O_NONBLOCK | \
102 __O_SYNC | O_DSYNC | O_CLOEXEC | \
103 O_LARGEFILE | O_NOATIME )
104
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -0500105extern const struct fsnotify_ops fanotify_fsnotify_ops;
Eric Paris11637e42009-12-17 21:24:25 -0500106
Jan Kara054c6362016-12-21 18:06:12 +0100107struct kmem_cache *fanotify_mark_cache __read_mostly;
Jan Kara7088f352020-03-24 17:04:20 +0100108struct kmem_cache *fanotify_fid_event_cachep __read_mostly;
109struct kmem_cache *fanotify_path_event_cachep __read_mostly;
Jan Karaf0834412014-04-03 14:46:33 -0700110struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
Eric Paris2a3edf82009-12-17 21:24:26 -0500111
Amir Goldstein5e469c82019-01-10 19:04:35 +0200112#define FANOTIFY_EVENT_ALIGN 4
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000113#define FANOTIFY_FID_INFO_HDR_LEN \
Amir Goldstein44d705b2020-03-19 17:10:22 +0200114 (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle))
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000115#define FANOTIFY_PIDFD_INFO_HDR_LEN \
116 sizeof(struct fanotify_event_info_pidfd)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200117
Amir Goldstein44d705b2020-03-19 17:10:22 +0200118static int fanotify_fid_info_len(int fh_len, int name_len)
Amir Goldsteind766b552020-03-19 17:10:20 +0200119{
Amir Goldstein44d705b2020-03-19 17:10:22 +0200120 int info_len = fh_len;
121
122 if (name_len)
123 info_len += name_len + 1;
124
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000125 return roundup(FANOTIFY_FID_INFO_HDR_LEN + info_len,
126 FANOTIFY_EVENT_ALIGN);
Amir Goldsteind766b552020-03-19 17:10:20 +0200127}
128
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300129static size_t fanotify_event_len(unsigned int info_mode,
130 struct fanotify_event *event)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200131{
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300132 size_t event_len = FAN_EVENT_METADATA_LEN;
133 struct fanotify_info *info;
134 int dir_fh_len;
135 int fh_len;
Amir Goldstein929943b2020-07-16 11:42:28 +0300136 int dot_len = 0;
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300137
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300138 if (!info_mode)
139 return event_len;
140
141 info = fanotify_event_info(event);
142 dir_fh_len = fanotify_event_dir_fh_len(event);
143 fh_len = fanotify_event_object_fh_len(event);
144
Amir Goldstein929943b2020-07-16 11:42:28 +0300145 if (dir_fh_len) {
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300146 event_len += fanotify_fid_info_len(dir_fh_len, info->name_len);
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000147 } else if ((info_mode & FAN_REPORT_NAME) &&
148 (event->mask & FAN_ONDIR)) {
Amir Goldstein929943b2020-07-16 11:42:28 +0300149 /*
150 * With group flag FAN_REPORT_NAME, if name was not recorded in
151 * event on a directory, we will report the name ".".
152 */
153 dot_len = 1;
154 }
Jan Karaafc894c2020-03-24 16:55:37 +0100155
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000156 if (info_mode & FAN_REPORT_PIDFD)
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300157 event_len += FANOTIFY_PIDFD_INFO_HDR_LEN;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000158
Amir Goldstein44d705b2020-03-19 17:10:22 +0200159 if (fh_len)
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300160 event_len += fanotify_fid_info_len(fh_len, dot_len);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200161
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300162 return event_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200163}
164
Eric Parisa1014f12009-12-17 21:24:26 -0500165/*
Amir Goldstein94e00d22021-03-04 12:48:25 +0200166 * Remove an hashed event from merge hash table.
167 */
168static void fanotify_unhash_event(struct fsnotify_group *group,
169 struct fanotify_event *event)
170{
171 assert_spin_locked(&group->notification_lock);
172
173 pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
174 group, event, fanotify_event_hash_bucket(group, event));
175
176 if (WARN_ON_ONCE(hlist_unhashed(&event->merge_list)))
177 return;
178
179 hlist_del_init(&event->merge_list);
180}
181
182/*
Jan Kara7088f352020-03-24 17:04:20 +0100183 * Get an fanotify notification event if one exists and is small
Eric Parisa1014f12009-12-17 21:24:26 -0500184 * enough to fit in "count". Return an error pointer if the count
Jan Kara40873282019-01-08 14:02:44 +0100185 * is not large enough. When permission event is dequeued, its state is
186 * updated accordingly.
Eric Parisa1014f12009-12-17 21:24:26 -0500187 */
Jan Kara7088f352020-03-24 17:04:20 +0100188static struct fanotify_event *get_one_event(struct fsnotify_group *group,
Eric Parisa1014f12009-12-17 21:24:26 -0500189 size_t count)
190{
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300191 size_t event_size;
Jan Kara7088f352020-03-24 17:04:20 +0100192 struct fanotify_event *event = NULL;
Amir Goldstein6f731712021-03-04 12:48:22 +0200193 struct fsnotify_event *fsn_event;
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000194 unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
Eric Parisa1014f12009-12-17 21:24:26 -0500195
196 pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
197
Jan Kara8c554462019-01-08 13:52:31 +0100198 spin_lock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200199 fsn_event = fsnotify_peek_first_event(group);
200 if (!fsn_event)
Jan Kara8c554462019-01-08 13:52:31 +0100201 goto out;
Eric Parisa1014f12009-12-17 21:24:26 -0500202
Amir Goldstein6f731712021-03-04 12:48:22 +0200203 event = FANOTIFY_E(fsn_event);
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300204 event_size = fanotify_event_len(info_mode, event);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200205
Jan Kara8c554462019-01-08 13:52:31 +0100206 if (event_size > count) {
Jan Kara7088f352020-03-24 17:04:20 +0100207 event = ERR_PTR(-EINVAL);
Jan Kara8c554462019-01-08 13:52:31 +0100208 goto out;
209 }
Amir Goldstein6f731712021-03-04 12:48:22 +0200210
211 /*
212 * Held the notification_lock the whole time, so this is the
213 * same event we peeked above.
214 */
215 fsnotify_remove_first_event(group);
Jan Kara7088f352020-03-24 17:04:20 +0100216 if (fanotify_is_perm_event(event->mask))
217 FANOTIFY_PERM(event)->state = FAN_EVENT_REPORTED;
Amir Goldstein94e00d22021-03-04 12:48:25 +0200218 if (fanotify_is_hashed_event(event->mask))
219 fanotify_unhash_event(group, event);
Jan Kara8c554462019-01-08 13:52:31 +0100220out:
221 spin_unlock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100222 return event;
Eric Parisa1014f12009-12-17 21:24:26 -0500223}
224
Jan Karaa741c2f2020-03-24 15:27:52 +0100225static int create_fd(struct fsnotify_group *group, struct path *path,
Jan Kara7053aee2014-01-21 15:48:14 -0800226 struct file **file)
Eric Parisa1014f12009-12-17 21:24:26 -0500227{
228 int client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500229 struct file *new_file;
230
Yann Droneaud0b37e092014-10-09 15:24:40 -0700231 client_fd = get_unused_fd_flags(group->fanotify_data.f_flags);
Eric Parisa1014f12009-12-17 21:24:26 -0500232 if (client_fd < 0)
233 return client_fd;
234
Eric Parisa1014f12009-12-17 21:24:26 -0500235 /*
236 * we need a new file handle for the userspace program so it can read even if it was
237 * originally opened O_WRONLY.
238 */
Jan Karaa741c2f2020-03-24 15:27:52 +0100239 new_file = dentry_open(path,
240 group->fanotify_data.f_flags | FMODE_NONOTIFY,
241 current_cred());
Eric Parisa1014f12009-12-17 21:24:26 -0500242 if (IS_ERR(new_file)) {
243 /*
244 * we still send an event even if we can't open the file. this
245 * can happen when say tasks are gone and we try to open their
246 * /proc files or we try to open a WRONLY file like in sysfs
247 * we just send the errno to userspace since there isn't much
248 * else we can do.
249 */
250 put_unused_fd(client_fd);
251 client_fd = PTR_ERR(new_file);
252 } else {
Al Viro352e3b22012-08-19 12:30:45 -0400253 *file = new_file;
Eric Parisa1014f12009-12-17 21:24:26 -0500254 }
255
Andreas Gruenbacher22aa4252009-12-17 21:24:26 -0500256 return client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500257}
258
Jan Kara40873282019-01-08 14:02:44 +0100259/*
260 * Finish processing of permission event by setting it to ANSWERED state and
261 * drop group->notification_lock.
262 */
263static void finish_permission_event(struct fsnotify_group *group,
264 struct fanotify_perm_event *event,
265 unsigned int response)
266 __releases(&group->notification_lock)
267{
Jan Karafabf7f22019-01-08 15:18:02 +0100268 bool destroy = false;
269
Jan Kara40873282019-01-08 14:02:44 +0100270 assert_spin_locked(&group->notification_lock);
271 event->response = response;
Jan Karafabf7f22019-01-08 15:18:02 +0100272 if (event->state == FAN_EVENT_CANCELED)
273 destroy = true;
274 else
275 event->state = FAN_EVENT_ANSWERED;
Jan Kara40873282019-01-08 14:02:44 +0100276 spin_unlock(&group->notification_lock);
Jan Karafabf7f22019-01-08 15:18:02 +0100277 if (destroy)
278 fsnotify_destroy_event(group, &event->fae.fse);
Jan Kara40873282019-01-08 14:02:44 +0100279}
280
Eric Parisb2d87902009-12-17 21:24:34 -0500281static int process_access_response(struct fsnotify_group *group,
282 struct fanotify_response *response_struct)
283{
Amir Goldstein33913992019-01-10 19:04:32 +0200284 struct fanotify_perm_event *event;
Jan Karaf0834412014-04-03 14:46:33 -0700285 int fd = response_struct->fd;
286 int response = response_struct->response;
Eric Parisb2d87902009-12-17 21:24:34 -0500287
288 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,
289 fd, response);
290 /*
291 * make sure the response is valid, if invalid we do nothing and either
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300292 * userspace can send a valid response or we will clean it up after the
Eric Parisb2d87902009-12-17 21:24:34 -0500293 * timeout
294 */
Steve Grubbde8cd832017-10-02 20:21:39 -0400295 switch (response & ~FAN_AUDIT) {
Eric Parisb2d87902009-12-17 21:24:34 -0500296 case FAN_ALLOW:
297 case FAN_DENY:
298 break;
299 default:
300 return -EINVAL;
301 }
302
303 if (fd < 0)
304 return -EINVAL;
305
Amir Goldstein96a71f22018-09-21 21:20:30 +0300306 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -0400307 return -EINVAL;
308
Jan Karaaf6a5112019-01-08 13:28:18 +0100309 spin_lock(&group->notification_lock);
310 list_for_each_entry(event, &group->fanotify_data.access_list,
311 fae.fse.list) {
312 if (event->fd != fd)
313 continue;
Eric Parisb2d87902009-12-17 21:24:34 -0500314
Jan Karaaf6a5112019-01-08 13:28:18 +0100315 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100316 finish_permission_event(group, event, response);
Jan Karaaf6a5112019-01-08 13:28:18 +0100317 wake_up(&group->fanotify_data.access_waitq);
318 return 0;
319 }
320 spin_unlock(&group->notification_lock);
Eric Parisb2d87902009-12-17 21:24:34 -0500321
Jan Karaaf6a5112019-01-08 13:28:18 +0100322 return -ENOENT;
Eric Parisb2d87902009-12-17 21:24:34 -0500323}
Eric Parisb2d87902009-12-17 21:24:34 -0500324
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000325static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,
326 int info_type, const char *name,
327 size_t name_len,
328 char __user *buf, size_t count)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200329{
330 struct fanotify_event_info_fid info = { };
331 struct file_handle handle = { };
Jan Karaafc894c2020-03-24 16:55:37 +0100332 unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200333 size_t fh_len = fh ? fh->len : 0;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200334 size_t info_len = fanotify_fid_info_len(fh_len, name_len);
335 size_t len = info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200336
Amir Goldstein44d705b2020-03-19 17:10:22 +0200337 pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n",
338 __func__, fh_len, name_len, info_len, count);
339
Amir Goldstein83b7a592020-07-16 11:42:26 +0300340 if (!fh_len)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200341 return 0;
342
Amir Goldstein44d705b2020-03-19 17:10:22 +0200343 if (WARN_ON_ONCE(len < sizeof(info) || len > count))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200344 return -EFAULT;
345
Amir Goldstein44d705b2020-03-19 17:10:22 +0200346 /*
347 * Copy event info fid header followed by variable sized file handle
348 * and optionally followed by variable sized filename.
349 */
Amir Goldstein83b7a592020-07-16 11:42:26 +0300350 switch (info_type) {
351 case FAN_EVENT_INFO_TYPE_FID:
352 case FAN_EVENT_INFO_TYPE_DFID:
353 if (WARN_ON_ONCE(name_len))
354 return -EFAULT;
355 break;
356 case FAN_EVENT_INFO_TYPE_DFID_NAME:
357 if (WARN_ON_ONCE(!name || !name_len))
358 return -EFAULT;
359 break;
360 default:
361 return -EFAULT;
362 }
363
364 info.hdr.info_type = info_type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200365 info.hdr.len = len;
Amir Goldsteind766b552020-03-19 17:10:20 +0200366 info.fsid = *fsid;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200367 if (copy_to_user(buf, &info, sizeof(info)))
368 return -EFAULT;
369
370 buf += sizeof(info);
371 len -= sizeof(info);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200372 if (WARN_ON_ONCE(len < sizeof(handle)))
373 return -EFAULT;
374
Jan Karaafc894c2020-03-24 16:55:37 +0100375 handle.handle_type = fh->type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200376 handle.handle_bytes = fh_len;
377 if (copy_to_user(buf, &handle, sizeof(handle)))
378 return -EFAULT;
379
380 buf += sizeof(handle);
381 len -= sizeof(handle);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200382 if (WARN_ON_ONCE(len < fh_len))
383 return -EFAULT;
384
Jan Karab2d22b62019-03-12 12:42:37 +0100385 /*
Amir Goldstein44d705b2020-03-19 17:10:22 +0200386 * For an inline fh and inline file name, copy through stack to exclude
387 * the copy from usercopy hardening protections.
Jan Karab2d22b62019-03-12 12:42:37 +0100388 */
Jan Karaafc894c2020-03-24 16:55:37 +0100389 fh_buf = fanotify_fh_buf(fh);
Jan Karab2d22b62019-03-12 12:42:37 +0100390 if (fh_len <= FANOTIFY_INLINE_FH_LEN) {
Jan Karaafc894c2020-03-24 16:55:37 +0100391 memcpy(bounce, fh_buf, fh_len);
392 fh_buf = bounce;
Jan Karab2d22b62019-03-12 12:42:37 +0100393 }
Jan Karaafc894c2020-03-24 16:55:37 +0100394 if (copy_to_user(buf, fh_buf, fh_len))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200395 return -EFAULT;
396
Amir Goldstein5e469c82019-01-10 19:04:35 +0200397 buf += fh_len;
398 len -= fh_len;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200399
400 if (name_len) {
401 /* Copy the filename with terminating null */
402 name_len++;
403 if (WARN_ON_ONCE(len < name_len))
404 return -EFAULT;
405
406 if (copy_to_user(buf, name, name_len))
407 return -EFAULT;
408
409 buf += name_len;
410 len -= name_len;
411 }
412
413 /* Pad with 0's */
Amir Goldstein5e469c82019-01-10 19:04:35 +0200414 WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
415 if (len > 0 && clear_user(buf, len))
416 return -EFAULT;
417
Amir Goldstein44d705b2020-03-19 17:10:22 +0200418 return info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200419}
420
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000421static int copy_pidfd_info_to_user(int pidfd,
422 char __user *buf,
423 size_t count)
424{
425 struct fanotify_event_info_pidfd info = { };
426 size_t info_len = FANOTIFY_PIDFD_INFO_HDR_LEN;
427
428 if (WARN_ON_ONCE(info_len > count))
429 return -EFAULT;
430
431 info.hdr.info_type = FAN_EVENT_INFO_TYPE_PIDFD;
432 info.hdr.len = info_len;
433 info.pidfd = pidfd;
434
435 if (copy_to_user(buf, &info, info_len))
436 return -EFAULT;
437
438 return info_len;
439}
440
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000441static int copy_info_records_to_user(struct fanotify_event *event,
442 struct fanotify_info *info,
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000443 unsigned int info_mode, int pidfd,
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000444 char __user *buf, size_t count)
445{
446 int ret, total_bytes = 0, info_type = 0;
447 unsigned int fid_mode = info_mode & FANOTIFY_FID_BITS;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000448 unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000449
450 /*
451 * Event info records order is as follows: dir fid + name, child fid.
452 */
453 if (fanotify_event_dir_fh_len(event)) {
454 info_type = info->name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME :
455 FAN_EVENT_INFO_TYPE_DFID;
456 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
457 fanotify_info_dir_fh(info),
458 info_type,
459 fanotify_info_name(info),
460 info->name_len, buf, count);
461 if (ret < 0)
462 return ret;
463
464 buf += ret;
465 count -= ret;
466 total_bytes += ret;
467 }
468
469 if (fanotify_event_object_fh_len(event)) {
470 const char *dot = NULL;
471 int dot_len = 0;
472
473 if (fid_mode == FAN_REPORT_FID || info_type) {
474 /*
475 * With only group flag FAN_REPORT_FID only type FID is
476 * reported. Second info record type is always FID.
477 */
478 info_type = FAN_EVENT_INFO_TYPE_FID;
479 } else if ((fid_mode & FAN_REPORT_NAME) &&
480 (event->mask & FAN_ONDIR)) {
481 /*
482 * With group flag FAN_REPORT_NAME, if name was not
483 * recorded in an event on a directory, report the name
484 * "." with info type DFID_NAME.
485 */
486 info_type = FAN_EVENT_INFO_TYPE_DFID_NAME;
487 dot = ".";
488 dot_len = 1;
489 } else if ((event->mask & ALL_FSNOTIFY_DIRENT_EVENTS) ||
490 (event->mask & FAN_ONDIR)) {
491 /*
492 * With group flag FAN_REPORT_DIR_FID, a single info
493 * record has type DFID for directory entry modification
494 * event and for event on a directory.
495 */
496 info_type = FAN_EVENT_INFO_TYPE_DFID;
497 } else {
498 /*
499 * With group flags FAN_REPORT_DIR_FID|FAN_REPORT_FID,
500 * a single info record has type FID for event on a
501 * non-directory, when there is no directory to report.
502 * For example, on FAN_DELETE_SELF event.
503 */
504 info_type = FAN_EVENT_INFO_TYPE_FID;
505 }
506
507 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
508 fanotify_event_object_fh(event),
509 info_type, dot, dot_len,
510 buf, count);
511 if (ret < 0)
512 return ret;
513
514 buf += ret;
515 count -= ret;
516 total_bytes += ret;
517 }
518
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000519 if (pidfd_mode) {
520 ret = copy_pidfd_info_to_user(pidfd, buf, count);
521 if (ret < 0)
522 return ret;
523
524 buf += ret;
525 count -= ret;
526 total_bytes += ret;
527 }
528
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000529 return total_bytes;
530}
531
Eric Parisa1014f12009-12-17 21:24:26 -0500532static ssize_t copy_event_to_user(struct fsnotify_group *group,
Jan Kara7088f352020-03-24 17:04:20 +0100533 struct fanotify_event *event,
Kees Cook5b03a472018-12-04 15:44:46 -0800534 char __user *buf, size_t count)
Eric Parisa1014f12009-12-17 21:24:26 -0500535{
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200536 struct fanotify_event_metadata metadata;
Jan Kara7088f352020-03-24 17:04:20 +0100537 struct path *path = fanotify_event_path(event);
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300538 struct fanotify_info *info = fanotify_event_info(event);
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000539 unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000540 unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200541 struct file *f = NULL;
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000542 int ret, pidfd = FAN_NOPIDFD, fd = FAN_NOFD;
Eric Parisa1014f12009-12-17 21:24:26 -0500543
Jan Kara7088f352020-03-24 17:04:20 +0100544 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
Eric Parisa1014f12009-12-17 21:24:26 -0500545
Gabriel Krisman Bertazib9928e82021-10-25 16:27:20 -0300546 metadata.event_len = fanotify_event_len(info_mode, event);
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200547 metadata.metadata_len = FAN_EVENT_METADATA_LEN;
548 metadata.vers = FANOTIFY_METADATA_VERSION;
549 metadata.reserved = 0;
550 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
551 metadata.pid = pid_vnr(event->pid);
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200552 /*
553 * For an unprivileged listener, event->pid can be used to identify the
554 * events generated by the listener process itself, without disclosing
555 * the pids of other processes.
556 */
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300557 if (FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200558 task_tgid(current) != event->pid)
559 metadata.pid = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500560
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300561 /*
562 * For now, fid mode is required for an unprivileged listener and
563 * fid mode does not report fd in events. Keep this check anyway
564 * for safety in case fid mode requirement is relaxed in the future
565 * to allow unprivileged listener to get events with no fd and no fid.
566 */
567 if (!FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
568 path && path->mnt && path->dentry) {
Jan Karaafc894c2020-03-24 16:55:37 +0100569 fd = create_fd(group, path, &f);
570 if (fd < 0)
571 return fd;
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200572 }
573 metadata.fd = fd;
574
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000575 if (pidfd_mode) {
576 /*
577 * Complain if the FAN_REPORT_PIDFD and FAN_REPORT_TID mutual
578 * exclusion is ever lifted. At the time of incoporating pidfd
579 * support within fanotify, the pidfd API only supported the
580 * creation of pidfds for thread-group leaders.
581 */
582 WARN_ON_ONCE(FAN_GROUP_FLAG(group, FAN_REPORT_TID));
583
584 /*
585 * The PIDTYPE_TGID check for an event->pid is performed
586 * preemptively in an attempt to catch out cases where the event
587 * listener reads events after the event generating process has
588 * already terminated. Report FAN_NOPIDFD to the event listener
589 * in those cases, with all other pidfd creation errors being
590 * reported as FAN_EPIDFD.
591 */
592 if (metadata.pid == 0 ||
593 !pid_has_task(event->pid, PIDTYPE_TGID)) {
594 pidfd = FAN_NOPIDFD;
595 } else {
596 pidfd = pidfd_create(event->pid, 0);
597 if (pidfd < 0)
598 pidfd = FAN_EPIDFD;
599 }
600 }
601
Al Viro352e3b22012-08-19 12:30:45 -0400602 ret = -EFAULT;
Kees Cook5b03a472018-12-04 15:44:46 -0800603 /*
604 * Sanity check copy size in case get_one_event() and
Fabian Frederickc5e443c2020-05-12 20:18:36 +0200605 * event_len sizes ever get out of sync.
Kees Cook5b03a472018-12-04 15:44:46 -0800606 */
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200607 if (WARN_ON_ONCE(metadata.event_len > count))
Al Viro352e3b22012-08-19 12:30:45 -0400608 goto out_close_fd;
609
Amir Goldstein5e469c82019-01-10 19:04:35 +0200610 if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN))
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200611 goto out_close_fd;
612
Amir Goldstein44d705b2020-03-19 17:10:22 +0200613 buf += FAN_EVENT_METADATA_LEN;
614 count -= FAN_EVENT_METADATA_LEN;
615
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200616 if (fanotify_is_perm_event(event->mask))
Jan Kara7088f352020-03-24 17:04:20 +0100617 FANOTIFY_PERM(event)->fd = fd;
Eric Parisb2d87902009-12-17 21:24:34 -0500618
Amir Goldstein44d705b2020-03-19 17:10:22 +0200619 if (f)
Al Viro3587b1b2012-11-18 19:19:00 +0000620 fd_install(fd, f);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200621
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000622 if (info_mode) {
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000623 ret = copy_info_records_to_user(event, info, info_mode, pidfd,
Matthew Bobrowski0aca67b2021-08-08 15:25:58 +1000624 buf, count);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200625 if (ret < 0)
Matthew Bobrowskif644bc42021-06-11 13:32:06 +1000626 goto out_close_fd;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200627 }
628
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200629 return metadata.event_len;
Eric Parisb2d87902009-12-17 21:24:34 -0500630
Eric Parisb2d87902009-12-17 21:24:34 -0500631out_close_fd:
Al Viro352e3b22012-08-19 12:30:45 -0400632 if (fd != FAN_NOFD) {
633 put_unused_fd(fd);
634 fput(f);
635 }
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +1000636
637 if (pidfd >= 0)
638 close_fd(pidfd);
639
Eric Parisb2d87902009-12-17 21:24:34 -0500640 return ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500641}
642
643/* intofiy userspace file descriptor functions */
Al Viro076ccb72017-07-03 01:02:18 -0400644static __poll_t fanotify_poll(struct file *file, poll_table *wait)
Eric Parisa1014f12009-12-17 21:24:26 -0500645{
646 struct fsnotify_group *group = file->private_data;
Al Viro076ccb72017-07-03 01:02:18 -0400647 __poll_t ret = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500648
649 poll_wait(file, &group->notification_waitq, wait);
Jan Karac21dbe22016-10-07 16:56:52 -0700650 spin_lock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500651 if (!fsnotify_notify_queue_is_empty(group))
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800652 ret = EPOLLIN | EPOLLRDNORM;
Jan Karac21dbe22016-10-07 16:56:52 -0700653 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500654
655 return ret;
656}
657
658static ssize_t fanotify_read(struct file *file, char __user *buf,
659 size_t count, loff_t *pos)
660{
661 struct fsnotify_group *group;
Jan Kara7088f352020-03-24 17:04:20 +0100662 struct fanotify_event *event;
Eric Parisa1014f12009-12-17 21:24:26 -0500663 char __user *start;
664 int ret;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100665 DEFINE_WAIT_FUNC(wait, woken_wake_function);
Eric Parisa1014f12009-12-17 21:24:26 -0500666
667 start = buf;
668 group = file->private_data;
669
670 pr_debug("%s: group=%p\n", __func__, group);
671
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100672 add_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500673 while (1) {
Jan Kara47aaabd2020-07-15 14:06:21 +0200674 /*
675 * User can supply arbitrarily large buffer. Avoid softlockups
676 * in case there are lots of available events.
677 */
678 cond_resched();
Jan Kara7088f352020-03-24 17:04:20 +0100679 event = get_one_event(group, count);
680 if (IS_ERR(event)) {
681 ret = PTR_ERR(event);
Jan Karad8aaab42014-04-03 14:46:35 -0700682 break;
683 }
684
Jan Kara7088f352020-03-24 17:04:20 +0100685 if (!event) {
Jan Karad8aaab42014-04-03 14:46:35 -0700686 ret = -EAGAIN;
687 if (file->f_flags & O_NONBLOCK)
Eric Parisa1014f12009-12-17 21:24:26 -0500688 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700689
690 ret = -ERESTARTSYS;
691 if (signal_pending(current))
Eric Parisa1014f12009-12-17 21:24:26 -0500692 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700693
694 if (start != buf)
695 break;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100696
697 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
Eric Parisa1014f12009-12-17 21:24:26 -0500698 continue;
699 }
700
Jan Kara7088f352020-03-24 17:04:20 +0100701 ret = copy_event_to_user(group, event, buf, count);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300702 if (unlikely(ret == -EOPENSTALE)) {
703 /*
704 * We cannot report events with stale fd so drop it.
705 * Setting ret to 0 will continue the event loop and
706 * do the right thing if there are no more events to
707 * read (i.e. return bytes read, -EAGAIN or wait).
708 */
709 ret = 0;
710 }
711
Jan Karad8aaab42014-04-03 14:46:35 -0700712 /*
713 * Permission events get queued to wait for response. Other
714 * events can be destroyed now.
715 */
Jan Kara7088f352020-03-24 17:04:20 +0100716 if (!fanotify_is_perm_event(event->mask)) {
717 fsnotify_destroy_event(group, &event->fse);
Jan Karad5078162014-04-03 14:46:36 -0700718 } else {
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300719 if (ret <= 0) {
Jan Kara40873282019-01-08 14:02:44 +0100720 spin_lock(&group->notification_lock);
721 finish_permission_event(group,
Jan Kara7088f352020-03-24 17:04:20 +0100722 FANOTIFY_PERM(event), FAN_DENY);
Jan Karad5078162014-04-03 14:46:36 -0700723 wake_up(&group->fanotify_data.access_waitq);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300724 } else {
725 spin_lock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100726 list_add_tail(&event->fse.list,
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300727 &group->fanotify_data.access_list);
728 spin_unlock(&group->notification_lock);
Jan Karad5078162014-04-03 14:46:36 -0700729 }
Jan Karad5078162014-04-03 14:46:36 -0700730 }
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300731 if (ret < 0)
732 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700733 buf += ret;
734 count -= ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500735 }
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100736 remove_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500737
Eric Parisa1014f12009-12-17 21:24:26 -0500738 if (start != buf && ret != -EFAULT)
739 ret = buf - start;
740 return ret;
741}
742
Eric Parisb2d87902009-12-17 21:24:34 -0500743static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
744{
Eric Parisb2d87902009-12-17 21:24:34 -0500745 struct fanotify_response response = { .fd = -1, .response = -1 };
746 struct fsnotify_group *group;
747 int ret;
748
Miklos Szeredi6685df32017-10-30 21:14:56 +0100749 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
750 return -EINVAL;
751
Eric Parisb2d87902009-12-17 21:24:34 -0500752 group = file->private_data;
753
Fabian Frederick5e236632020-05-12 20:19:21 +0200754 if (count < sizeof(response))
755 return -EINVAL;
756
757 count = sizeof(response);
Eric Parisb2d87902009-12-17 21:24:34 -0500758
759 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
760
761 if (copy_from_user(&response, buf, count))
762 return -EFAULT;
763
764 ret = process_access_response(group, &response);
765 if (ret < 0)
766 count = ret;
767
768 return count;
Eric Parisb2d87902009-12-17 21:24:34 -0500769}
770
Eric Paris52c923d2009-12-17 21:24:26 -0500771static int fanotify_release(struct inode *ignored, struct file *file)
772{
773 struct fsnotify_group *group = file->private_data;
Amir Goldstein6f731712021-03-04 12:48:22 +0200774 struct fsnotify_event *fsn_event;
Andrew Morton19ba54f2010-10-28 17:21:59 -0400775
Jan Kara5838d442014-08-06 16:03:28 -0700776 /*
Jan Kara96d41012016-09-19 14:44:30 -0700777 * Stop new events from arriving in the notification queue. since
778 * userspace cannot use fanotify fd anymore, no event can enter or
779 * leave access_list by now either.
780 */
781 fsnotify_group_stop_queueing(group);
782
783 /*
784 * Process all permission events on access_list and notification queue
785 * and simulate reply from userspace.
Jan Kara5838d442014-08-06 16:03:28 -0700786 */
Jan Kara073f6552016-10-07 16:56:55 -0700787 spin_lock(&group->notification_lock);
Jan Karaca6f8692019-01-09 13:21:01 +0100788 while (!list_empty(&group->fanotify_data.access_list)) {
Jan Kara7088f352020-03-24 17:04:20 +0100789 struct fanotify_perm_event *event;
790
Jan Karaca6f8692019-01-09 13:21:01 +0100791 event = list_first_entry(&group->fanotify_data.access_list,
792 struct fanotify_perm_event, fae.fse.list);
Jan Karaf0834412014-04-03 14:46:33 -0700793 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100794 finish_permission_event(group, event, FAN_ALLOW);
795 spin_lock(&group->notification_lock);
Eric Paris2eebf582010-08-18 12:25:50 -0400796 }
Eric Paris2eebf582010-08-18 12:25:50 -0400797
Jan Kara5838d442014-08-06 16:03:28 -0700798 /*
Jan Kara96d41012016-09-19 14:44:30 -0700799 * Destroy all non-permission events. For permission events just
800 * dequeue them and set the response. They will be freed once the
801 * response is consumed and fanotify_get_response() returns.
Jan Kara5838d442014-08-06 16:03:28 -0700802 */
Amir Goldstein6f731712021-03-04 12:48:22 +0200803 while ((fsn_event = fsnotify_remove_first_event(group))) {
804 struct fanotify_event *event = FANOTIFY_E(fsn_event);
Jan Kara7088f352020-03-24 17:04:20 +0100805
Jan Kara7088f352020-03-24 17:04:20 +0100806 if (!(event->mask & FANOTIFY_PERM_EVENTS)) {
Jan Karac21dbe22016-10-07 16:56:52 -0700807 spin_unlock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200808 fsnotify_destroy_event(group, fsn_event);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100809 } else {
Jan Kara7088f352020-03-24 17:04:20 +0100810 finish_permission_event(group, FANOTIFY_PERM(event),
Jan Kara40873282019-01-08 14:02:44 +0100811 FAN_ALLOW);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100812 }
Jan Kara40873282019-01-08 14:02:44 +0100813 spin_lock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700814 }
Jan Karac21dbe22016-10-07 16:56:52 -0700815 spin_unlock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700816
817 /* Response for all permission events it set, wakeup waiters */
Eric Paris2eebf582010-08-18 12:25:50 -0400818 wake_up(&group->fanotify_data.access_waitq);
Eric Paris0a6b6bd2011-10-14 17:43:39 -0400819
Eric Paris52c923d2009-12-17 21:24:26 -0500820 /* matches the fanotify_init->fsnotify_alloc_group */
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200821 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -0500822
823 return 0;
824}
825
Eric Parisa1014f12009-12-17 21:24:26 -0500826static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
827{
828 struct fsnotify_group *group;
Jan Kara7053aee2014-01-21 15:48:14 -0800829 struct fsnotify_event *fsn_event;
Eric Parisa1014f12009-12-17 21:24:26 -0500830 void __user *p;
831 int ret = -ENOTTY;
832 size_t send_len = 0;
833
834 group = file->private_data;
835
836 p = (void __user *) arg;
837
838 switch (cmd) {
839 case FIONREAD:
Jan Karac21dbe22016-10-07 16:56:52 -0700840 spin_lock(&group->notification_lock);
Jan Kara7053aee2014-01-21 15:48:14 -0800841 list_for_each_entry(fsn_event, &group->notification_list, list)
Eric Parisa1014f12009-12-17 21:24:26 -0500842 send_len += FAN_EVENT_METADATA_LEN;
Jan Karac21dbe22016-10-07 16:56:52 -0700843 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500844 ret = put_user(send_len, (int __user *) p);
845 break;
846 }
847
848 return ret;
849}
850
Eric Paris52c923d2009-12-17 21:24:26 -0500851static const struct file_operations fanotify_fops = {
Cyrill Gorcunovbe771962012-12-17 16:05:12 -0800852 .show_fdinfo = fanotify_show_fdinfo,
Eric Parisa1014f12009-12-17 21:24:26 -0500853 .poll = fanotify_poll,
854 .read = fanotify_read,
Eric Parisb2d87902009-12-17 21:24:34 -0500855 .write = fanotify_write,
Eric Paris52c923d2009-12-17 21:24:26 -0500856 .fasync = NULL,
857 .release = fanotify_release,
Eric Parisa1014f12009-12-17 21:24:26 -0500858 .unlocked_ioctl = fanotify_ioctl,
Arnd Bergmann1832f2d2018-09-11 21:59:08 +0200859 .compat_ioctl = compat_ptr_ioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200860 .llseek = noop_llseek,
Eric Paris52c923d2009-12-17 21:24:26 -0500861};
862
Eric Paris2a3edf82009-12-17 21:24:26 -0500863static int fanotify_find_path(int dfd, const char __user *filename,
Aaron Goidelac5656d2019-08-12 11:20:00 -0400864 struct path *path, unsigned int flags, __u64 mask,
865 unsigned int obj_type)
Eric Paris2a3edf82009-12-17 21:24:26 -0500866{
867 int ret;
868
869 pr_debug("%s: dfd=%d filename=%p flags=%x\n", __func__,
870 dfd, filename, flags);
871
872 if (filename == NULL) {
Al Viro2903ff02012-08-28 12:52:22 -0400873 struct fd f = fdget(dfd);
Eric Paris2a3edf82009-12-17 21:24:26 -0500874
875 ret = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -0400876 if (!f.file)
Eric Paris2a3edf82009-12-17 21:24:26 -0500877 goto out;
878
879 ret = -ENOTDIR;
880 if ((flags & FAN_MARK_ONLYDIR) &&
Al Viro496ad9a2013-01-23 17:07:38 -0500881 !(S_ISDIR(file_inode(f.file)->i_mode))) {
Al Viro2903ff02012-08-28 12:52:22 -0400882 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500883 goto out;
884 }
885
Al Viro2903ff02012-08-28 12:52:22 -0400886 *path = f.file->f_path;
Eric Paris2a3edf82009-12-17 21:24:26 -0500887 path_get(path);
Al Viro2903ff02012-08-28 12:52:22 -0400888 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500889 } else {
890 unsigned int lookup_flags = 0;
891
892 if (!(flags & FAN_MARK_DONT_FOLLOW))
893 lookup_flags |= LOOKUP_FOLLOW;
894 if (flags & FAN_MARK_ONLYDIR)
895 lookup_flags |= LOOKUP_DIRECTORY;
896
897 ret = user_path_at(dfd, filename, lookup_flags, path);
898 if (ret)
899 goto out;
900 }
901
902 /* you can only watch an inode if you have read permissions on it */
Christian Brauner02f92b32021-01-21 14:19:22 +0100903 ret = path_permission(path, MAY_READ);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400904 if (ret) {
905 path_put(path);
906 goto out;
907 }
908
909 ret = security_path_notify(path, mask, obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -0500910 if (ret)
911 path_put(path);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400912
Eric Paris2a3edf82009-12-17 21:24:26 -0500913out:
914 return ret;
915}
916
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500917static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300918 __u32 mask, unsigned int flags,
919 __u32 umask, int *destroy)
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500920{
Lino Sanfilippod2c18742015-02-10 14:08:24 -0800921 __u32 oldmask = 0;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500922
Amir Goldstein4ed68142020-07-16 11:42:14 +0300923 /* umask bits cannot be removed by user */
924 mask &= ~umask;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500925 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500926 if (!(flags & FAN_MARK_IGNORED_MASK)) {
927 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +0300928 fsn_mark->mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500929 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +0300930 fsn_mark->ignored_mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500931 }
Amir Goldstein4ed68142020-07-16 11:42:14 +0300932 /*
933 * We need to keep the mark around even if remaining mask cannot
934 * result in any events (e.g. mask == FAN_ONDIR) to support incremenal
935 * changes to the mask.
936 * Destroy mark when only umask bits remain.
937 */
938 *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500939 spin_unlock(&fsn_mark->lock);
940
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500941 return mask & oldmask;
942}
943
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300944static int fanotify_remove_mark(struct fsnotify_group *group,
945 fsnotify_connp_t *connp, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300946 unsigned int flags, __u32 umask)
Eric Paris88826272009-12-17 21:24:28 -0500947{
948 struct fsnotify_mark *fsn_mark = NULL;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500949 __u32 removed;
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200950 int destroy_mark;
Eric Paris88826272009-12-17 21:24:28 -0500951
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700952 mutex_lock(&group->mark_mutex);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300953 fsn_mark = fsnotify_find_mark(connp, group);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700954 if (!fsn_mark) {
955 mutex_unlock(&group->mark_mutex);
Eric Paris88826272009-12-17 21:24:28 -0500956 return -ENOENT;
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700957 }
Eric Paris88826272009-12-17 21:24:28 -0500958
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200959 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300960 umask, &destroy_mark);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +0300961 if (removed & fsnotify_conn_mask(fsn_mark->connector))
962 fsnotify_recalc_mask(fsn_mark->connector);
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200963 if (destroy_mark)
Jan Kara4712e7222015-09-04 15:43:12 -0700964 fsnotify_detach_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700965 mutex_unlock(&group->mark_mutex);
Jan Kara4712e7222015-09-04 15:43:12 -0700966 if (destroy_mark)
967 fsnotify_free_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700968
Jan Karab1362ed2016-12-21 16:28:45 +0100969 /* matches the fsnotify_find_mark() */
Eric Paris2a3edf82009-12-17 21:24:26 -0500970 fsnotify_put_mark(fsn_mark);
Eric Paris2a3edf82009-12-17 21:24:26 -0500971 return 0;
972}
973
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300974static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
975 struct vfsmount *mnt, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300976 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300977{
978 return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300979 mask, flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300980}
981
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300982static int fanotify_remove_sb_mark(struct fsnotify_group *group,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300983 struct super_block *sb, __u32 mask,
984 unsigned int flags, __u32 umask)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300985{
Amir Goldstein4ed68142020-07-16 11:42:14 +0300986 return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
987 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300988}
989
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300990static int fanotify_remove_inode_mark(struct fsnotify_group *group,
991 struct inode *inode, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300992 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300993{
994 return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300995 flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300996}
997
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500998static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
999 __u32 mask,
1000 unsigned int flags)
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001001{
Eric Paris192ca4d2010-10-28 17:21:59 -04001002 __u32 oldmask = -1;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001003
1004 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001005 if (!(flags & FAN_MARK_IGNORED_MASK)) {
1006 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +03001007 fsn_mark->mask |= mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001008 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +03001009 fsn_mark->ignored_mask |= mask;
Eric Parisc9778a92009-12-17 21:24:33 -05001010 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
1011 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001012 }
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001013 spin_unlock(&fsn_mark->lock);
1014
1015 return mask & ~oldmask;
1016}
1017
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001018static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
Amir Goldsteinb812a9f2018-06-23 17:54:48 +03001019 fsnotify_connp_t *connp,
Amir Goldstein77115222019-01-10 19:04:37 +02001020 unsigned int type,
1021 __kernel_fsid_t *fsid)
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001022{
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001023 struct ucounts *ucounts = group->fanotify_data.ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001024 struct fsnotify_mark *mark;
1025 int ret;
1026
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001027 /*
1028 * Enforce per user marks limits per user in all containing user ns.
1029 * A group with FAN_UNLIMITED_MARKS does not contribute to mark count
1030 * in the limited groups account.
1031 */
1032 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS) &&
1033 !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001034 return ERR_PTR(-ENOSPC);
1035
1036 mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001037 if (!mark) {
1038 ret = -ENOMEM;
1039 goto out_dec_ucounts;
1040 }
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001041
Jan Kara054c6362016-12-21 18:06:12 +01001042 fsnotify_init_mark(mark, group);
Amir Goldstein77115222019-01-10 19:04:37 +02001043 ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001044 if (ret) {
1045 fsnotify_put_mark(mark);
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001046 goto out_dec_ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001047 }
1048
1049 return mark;
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001050
1051out_dec_ucounts:
1052 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
1053 dec_ucount(ucounts, UCOUNT_FANOTIFY_MARKS);
1054 return ERR_PTR(ret);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001055}
1056
1057
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001058static int fanotify_add_mark(struct fsnotify_group *group,
1059 fsnotify_connp_t *connp, unsigned int type,
Amir Goldstein77115222019-01-10 19:04:37 +02001060 __u32 mask, unsigned int flags,
1061 __kernel_fsid_t *fsid)
Eric Paris2a3edf82009-12-17 21:24:26 -05001062{
1063 struct fsnotify_mark *fsn_mark;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -05001064 __u32 added;
Eric Paris2a3edf82009-12-17 21:24:26 -05001065
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001066 mutex_lock(&group->mark_mutex);
Amir Goldsteinb812a9f2018-06-23 17:54:48 +03001067 fsn_mark = fsnotify_find_mark(connp, group);
Eric Paris88826272009-12-17 21:24:28 -05001068 if (!fsn_mark) {
Amir Goldstein77115222019-01-10 19:04:37 +02001069 fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001070 if (IS_ERR(fsn_mark)) {
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001071 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001072 return PTR_ERR(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -07001073 }
Eric Paris88826272009-12-17 21:24:28 -05001074 }
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001075 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +03001076 if (added & ~fsnotify_conn_mask(fsn_mark->connector))
1077 fsnotify_recalc_mask(fsn_mark->connector);
Jan Karac9747642016-12-14 13:53:46 +01001078 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001079
Lino Sanfilippofa218ab2010-11-09 18:18:16 +01001080 fsnotify_put_mark(fsn_mark);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -07001081 return 0;
Eric Paris88826272009-12-17 21:24:28 -05001082}
1083
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001084static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
1085 struct vfsmount *mnt, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +02001086 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001087{
1088 return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001089 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001090}
1091
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001092static int fanotify_add_sb_mark(struct fsnotify_group *group,
Amir Goldstein77115222019-01-10 19:04:37 +02001093 struct super_block *sb, __u32 mask,
1094 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001095{
1096 return fanotify_add_mark(group, &sb->s_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001097 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001098}
1099
Andreas Gruenbacher52202df2009-12-17 21:24:28 -05001100static int fanotify_add_inode_mark(struct fsnotify_group *group,
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001101 struct inode *inode, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +02001102 unsigned int flags, __kernel_fsid_t *fsid)
Eric Paris88826272009-12-17 21:24:28 -05001103{
Eric Paris88826272009-12-17 21:24:28 -05001104 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
Eric Paris2a3edf82009-12-17 21:24:26 -05001105
Eric Paris5322a592010-10-28 17:21:57 -04001106 /*
1107 * If some other task has this inode open for write we should not add
1108 * an ignored mark, unless that ignored mark is supposed to survive
1109 * modification changes anyway.
1110 */
1111 if ((flags & FAN_MARK_IGNORED_MASK) &&
1112 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
Nikolay Borisovac9498d2018-12-11 10:27:23 +02001113 inode_is_open_for_write(inode))
Eric Paris5322a592010-10-28 17:21:57 -04001114 return 0;
1115
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001116 return fanotify_add_mark(group, &inode->i_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001117 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
Eric Paris88826272009-12-17 21:24:28 -05001118}
Eric Paris2a3edf82009-12-17 21:24:26 -05001119
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001120static struct fsnotify_event *fanotify_alloc_overflow_event(void)
1121{
1122 struct fanotify_event *oevent;
1123
1124 oevent = kmalloc(sizeof(*oevent), GFP_KERNEL_ACCOUNT);
1125 if (!oevent)
1126 return NULL;
1127
1128 fanotify_init_event(oevent, 0, FS_Q_OVERFLOW);
1129 oevent->type = FANOTIFY_EVENT_TYPE_OVERFLOW;
1130
1131 return &oevent->fse;
1132}
1133
Amir Goldstein94e00d22021-03-04 12:48:25 +02001134static struct hlist_head *fanotify_alloc_merge_hash(void)
1135{
1136 struct hlist_head *hash;
1137
1138 hash = kmalloc(sizeof(struct hlist_head) << FANOTIFY_HTABLE_BITS,
1139 GFP_KERNEL_ACCOUNT);
1140 if (!hash)
1141 return NULL;
1142
1143 __hash_init(hash, FANOTIFY_HTABLE_SIZE);
1144
1145 return hash;
1146}
1147
Eric Paris52c923d2009-12-17 21:24:26 -05001148/* fanotify syscalls */
Eric Paris08ae8932010-05-27 09:41:40 -04001149SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
Eric Paris11637e42009-12-17 21:24:25 -05001150{
Eric Paris52c923d2009-12-17 21:24:26 -05001151 struct fsnotify_group *group;
1152 int f_flags, fd;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001153 unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
1154 unsigned int class = flags & FANOTIFY_CLASS_BITS;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001155 unsigned int internal_flags = 0;
Eric Paris52c923d2009-12-17 21:24:26 -05001156
Amir Goldstein96a71f22018-09-21 21:20:30 +03001157 pr_debug("%s: flags=%x event_f_flags=%x\n",
1158 __func__, flags, event_f_flags);
Eric Paris52c923d2009-12-17 21:24:26 -05001159
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001160 if (!capable(CAP_SYS_ADMIN)) {
1161 /*
1162 * An unprivileged user can setup an fanotify group with
1163 * limited functionality - an unprivileged group is limited to
1164 * notification events with file handles and it cannot use
1165 * unlimited queue/marks.
1166 */
1167 if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode)
1168 return -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001169
1170 /*
1171 * Setting the internal flag FANOTIFY_UNPRIV on the group
1172 * prevents setting mount/filesystem marks on this group and
1173 * prevents reporting pid and open fd in events.
1174 */
1175 internal_flags |= FANOTIFY_UNPRIV;
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001176 }
Eric Paris52c923d2009-12-17 21:24:26 -05001177
Steve Grubbde8cd832017-10-02 20:21:39 -04001178#ifdef CONFIG_AUDITSYSCALL
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001179 if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -04001180#else
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001181 if (flags & ~FANOTIFY_INIT_FLAGS)
Steve Grubbde8cd832017-10-02 20:21:39 -04001182#endif
Eric Paris52c923d2009-12-17 21:24:26 -05001183 return -EINVAL;
1184
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +10001185 /*
1186 * A pidfd can only be returned for a thread-group leader; thus
1187 * FAN_REPORT_PIDFD and FAN_REPORT_TID need to remain mutually
1188 * exclusive.
1189 */
1190 if ((flags & FAN_REPORT_PIDFD) && (flags & FAN_REPORT_TID))
1191 return -EINVAL;
1192
Heinrich Schuchardt48149e92014-06-04 16:05:44 -07001193 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
1194 return -EINVAL;
1195
1196 switch (event_f_flags & O_ACCMODE) {
1197 case O_RDONLY:
1198 case O_RDWR:
1199 case O_WRONLY:
1200 break;
1201 default:
1202 return -EINVAL;
1203 }
1204
Amir Goldstein83b7a592020-07-16 11:42:26 +03001205 if (fid_mode && class != FAN_CLASS_NOTIF)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001206 return -EINVAL;
1207
Amir Goldstein929943b2020-07-16 11:42:28 +03001208 /*
Amir Goldstein929943b2020-07-16 11:42:28 +03001209 * Child name is reported with parent fid so requires dir fid.
Amir Goldstein691d9762020-07-16 11:42:30 +03001210 * We can report both child fid and dir fid with or without name.
Amir Goldstein929943b2020-07-16 11:42:28 +03001211 */
Amir Goldstein691d9762020-07-16 11:42:30 +03001212 if ((fid_mode & FAN_REPORT_NAME) && !(fid_mode & FAN_REPORT_DIR_FID))
Amir Goldstein83b7a592020-07-16 11:42:26 +03001213 return -EINVAL;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001214
Eric Parisb2d87902009-12-17 21:24:34 -05001215 f_flags = O_RDWR | FMODE_NONOTIFY;
Eric Paris52c923d2009-12-17 21:24:26 -05001216 if (flags & FAN_CLOEXEC)
1217 f_flags |= O_CLOEXEC;
1218 if (flags & FAN_NONBLOCK)
1219 f_flags |= O_NONBLOCK;
1220
1221 /* fsnotify_alloc_group takes a ref. Dropped in fanotify_release */
Shakeel Buttac7b79f2020-12-19 20:46:08 -08001222 group = fsnotify_alloc_user_group(&fanotify_fsnotify_ops);
Eric Paris26379192010-11-23 23:48:26 -05001223 if (IS_ERR(group)) {
Eric Paris52c923d2009-12-17 21:24:26 -05001224 return PTR_ERR(group);
Eric Paris26379192010-11-23 23:48:26 -05001225 }
Eric Paris52c923d2009-12-17 21:24:26 -05001226
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001227 /* Enforce groups limits per user in all containing user ns */
1228 group->fanotify_data.ucounts = inc_ucount(current_user_ns(),
1229 current_euid(),
1230 UCOUNT_FANOTIFY_GROUPS);
1231 if (!group->fanotify_data.ucounts) {
1232 fd = -EMFILE;
1233 goto out_destroy_group;
1234 }
1235
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001236 group->fanotify_data.flags = flags | internal_flags;
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001237 group->memcg = get_mem_cgroup_from_mm(current->mm);
Eric Paris4afeff82010-10-28 17:21:58 -04001238
Amir Goldstein94e00d22021-03-04 12:48:25 +02001239 group->fanotify_data.merge_hash = fanotify_alloc_merge_hash();
1240 if (!group->fanotify_data.merge_hash) {
1241 fd = -ENOMEM;
1242 goto out_destroy_group;
1243 }
1244
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001245 group->overflow_event = fanotify_alloc_overflow_event();
1246 if (unlikely(!group->overflow_event)) {
Jan Karaff57cd52014-02-21 19:14:11 +01001247 fd = -ENOMEM;
1248 goto out_destroy_group;
1249 }
Jan Karaff57cd52014-02-21 19:14:11 +01001250
Will Woods1e2ee492014-05-06 12:50:10 -07001251 if (force_o_largefile())
1252 event_f_flags |= O_LARGEFILE;
Eric Paris80af2582010-07-28 10:18:37 -04001253 group->fanotify_data.f_flags = event_f_flags;
Eric Paris9e66e422009-12-17 21:24:34 -05001254 init_waitqueue_head(&group->fanotify_data.access_waitq);
1255 INIT_LIST_HEAD(&group->fanotify_data.access_list);
Amir Goldstein83b7a592020-07-16 11:42:26 +03001256 switch (class) {
Eric Paris4231a232010-10-28 17:21:56 -04001257 case FAN_CLASS_NOTIF:
1258 group->priority = FS_PRIO_0;
1259 break;
1260 case FAN_CLASS_CONTENT:
1261 group->priority = FS_PRIO_1;
1262 break;
1263 case FAN_CLASS_PRE_CONTENT:
1264 group->priority = FS_PRIO_2;
1265 break;
1266 default:
1267 fd = -EINVAL;
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001268 goto out_destroy_group;
Eric Paris4231a232010-10-28 17:21:56 -04001269 }
Eric Pariscb2d4292009-12-17 21:24:34 -05001270
Eric Paris5dd03f52010-10-28 17:21:57 -04001271 if (flags & FAN_UNLIMITED_QUEUE) {
1272 fd = -EPERM;
1273 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001274 goto out_destroy_group;
Eric Paris5dd03f52010-10-28 17:21:57 -04001275 group->max_events = UINT_MAX;
1276 } else {
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001277 group->max_events = fanotify_max_queued_events;
Eric Paris5dd03f52010-10-28 17:21:57 -04001278 }
Eric Paris2529a0d2010-10-28 17:21:57 -04001279
Eric Parisac7e22d2010-10-28 17:21:58 -04001280 if (flags & FAN_UNLIMITED_MARKS) {
1281 fd = -EPERM;
1282 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001283 goto out_destroy_group;
Eric Parisac7e22d2010-10-28 17:21:58 -04001284 }
Eric Parise7099d82010-10-28 17:21:57 -04001285
Steve Grubbde8cd832017-10-02 20:21:39 -04001286 if (flags & FAN_ENABLE_AUDIT) {
1287 fd = -EPERM;
1288 if (!capable(CAP_AUDIT_WRITE))
1289 goto out_destroy_group;
Steve Grubbde8cd832017-10-02 20:21:39 -04001290 }
1291
Eric Paris52c923d2009-12-17 21:24:26 -05001292 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
1293 if (fd < 0)
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001294 goto out_destroy_group;
Eric Paris52c923d2009-12-17 21:24:26 -05001295
1296 return fd;
1297
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001298out_destroy_group:
1299 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -05001300 return fd;
Eric Paris11637e42009-12-17 21:24:25 -05001301}
Eric Parisbbaa4162009-12-17 21:24:26 -05001302
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001303static int fanotify_test_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001304{
Amir Goldstein73072282019-01-10 19:04:39 +02001305 __kernel_fsid_t root_fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001306 int err;
1307
1308 /*
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001309 * Make sure dentry is not of a filesystem with zero fsid (e.g. fuse).
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001310 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001311 err = vfs_get_fsid(dentry, fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001312 if (err)
1313 return err;
1314
Amir Goldstein73072282019-01-10 19:04:39 +02001315 if (!fsid->val[0] && !fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001316 return -ENODEV;
1317
1318 /*
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001319 * Make sure dentry is not of a filesystem subvolume (e.g. btrfs)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001320 * which uses a different fsid than sb root.
1321 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001322 err = vfs_get_fsid(dentry->d_sb->s_root, &root_fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001323 if (err)
1324 return err;
1325
Amir Goldstein73072282019-01-10 19:04:39 +02001326 if (root_fsid.val[0] != fsid->val[0] ||
1327 root_fsid.val[1] != fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001328 return -EXDEV;
1329
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001330 return 0;
1331}
1332
1333/* Check if filesystem can encode a unique fid */
1334static int fanotify_test_fid(struct dentry *dentry)
1335{
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001336 /*
1337 * We need to make sure that the file system supports at least
1338 * encoding a file handle so user can use name_to_handle_at() to
1339 * compare fid returned with event to the file handle of watched
1340 * objects. However, name_to_handle_at() requires that the
1341 * filesystem also supports decoding file handles.
1342 */
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001343 if (!dentry->d_sb->s_export_op ||
1344 !dentry->d_sb->s_export_op->fh_to_dentry)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001345 return -EOPNOTSUPP;
1346
1347 return 0;
1348}
1349
Jan Kara0b3b0942019-05-15 16:28:34 +02001350static int fanotify_events_supported(struct path *path, __u64 mask)
1351{
1352 /*
1353 * Some filesystems such as 'proc' acquire unusual locks when opening
1354 * files. For them fanotify permission events have high chances of
1355 * deadlocking the system - open done when reporting fanotify event
1356 * blocks on this "unusual" lock while another process holding the lock
1357 * waits for fanotify permission event to be answered. Just disallow
1358 * permission events for such filesystems.
1359 */
1360 if (mask & FANOTIFY_PERM_EVENTS &&
1361 path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
1362 return -EINVAL;
1363 return 0;
1364}
1365
Dominik Brodowski183caa32018-03-17 15:06:11 +01001366static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1367 int dfd, const char __user *pathname)
Eric Parisbbaa4162009-12-17 21:24:26 -05001368{
Eric Paris0ff21db2009-12-17 21:24:29 -05001369 struct inode *inode = NULL;
1370 struct vfsmount *mnt = NULL;
Eric Paris2a3edf82009-12-17 21:24:26 -05001371 struct fsnotify_group *group;
Al Viro2903ff02012-08-28 12:52:22 -04001372 struct fd f;
Eric Paris2a3edf82009-12-17 21:24:26 -05001373 struct path path;
Amir Goldstein73072282019-01-10 19:04:39 +02001374 __kernel_fsid_t __fsid, *fsid = NULL;
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001375 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001376 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
Amir Goldstein3ef86652020-07-16 11:42:13 +03001377 bool ignored = flags & FAN_MARK_IGNORED_MASK;
Amir Goldsteind809daf2020-07-16 11:42:12 +03001378 unsigned int obj_type, fid_mode;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001379 u32 umask = 0;
Al Viro2903ff02012-08-28 12:52:22 -04001380 int ret;
Eric Paris2a3edf82009-12-17 21:24:26 -05001381
1382 pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
1383 __func__, fanotify_fd, flags, dfd, pathname, mask);
1384
1385 /* we only use the lower 32 bits as of right now. */
Christian Brauner22d483b2021-03-25 09:37:43 +01001386 if (upper_32_bits(mask))
Eric Paris2a3edf82009-12-17 21:24:26 -05001387 return -EINVAL;
1388
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001389 if (flags & ~FANOTIFY_MARK_FLAGS)
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001390 return -EINVAL;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001391
1392 switch (mark_type) {
1393 case FAN_MARK_INODE:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001394 obj_type = FSNOTIFY_OBJ_TYPE_INODE;
1395 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001396 case FAN_MARK_MOUNT:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001397 obj_type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
1398 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001399 case FAN_MARK_FILESYSTEM:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001400 obj_type = FSNOTIFY_OBJ_TYPE_SB;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001401 break;
1402 default:
1403 return -EINVAL;
1404 }
1405
Eric Paris4d926042009-12-17 21:24:34 -05001406 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001407 case FAN_MARK_ADD:
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001408 case FAN_MARK_REMOVE:
Lino Sanfilippo1734dee2010-11-22 18:46:33 +01001409 if (!mask)
1410 return -EINVAL;
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001411 break;
Eric Paris4d926042009-12-17 21:24:34 -05001412 case FAN_MARK_FLUSH:
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001413 if (flags & ~(FANOTIFY_MARK_TYPE_BITS | FAN_MARK_FLUSH))
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001414 return -EINVAL;
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001415 break;
1416 default:
1417 return -EINVAL;
1418 }
Eric Paris8fcd6522010-10-28 17:21:59 -04001419
Miklos Szeredi6685df32017-10-30 21:14:56 +01001420 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001421 valid_mask |= FANOTIFY_PERM_EVENTS;
Miklos Szeredi6685df32017-10-30 21:14:56 +01001422
1423 if (mask & ~valid_mask)
Eric Paris2a3edf82009-12-17 21:24:26 -05001424 return -EINVAL;
1425
Amir Goldstein3ef86652020-07-16 11:42:13 +03001426 /* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */
1427 if (ignored)
1428 mask &= ~FANOTIFY_EVENT_FLAGS;
1429
Al Viro2903ff02012-08-28 12:52:22 -04001430 f = fdget(fanotify_fd);
1431 if (unlikely(!f.file))
Eric Paris2a3edf82009-12-17 21:24:26 -05001432 return -EBADF;
1433
1434 /* verify that this is indeed an fanotify instance */
1435 ret = -EINVAL;
Al Viro2903ff02012-08-28 12:52:22 -04001436 if (unlikely(f.file->f_op != &fanotify_fops))
Eric Paris2a3edf82009-12-17 21:24:26 -05001437 goto fput_and_out;
Al Viro2903ff02012-08-28 12:52:22 -04001438 group = f.file->private_data;
Eric Paris4231a232010-10-28 17:21:56 -04001439
1440 /*
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001441 * An unprivileged user is not allowed to setup mount nor filesystem
1442 * marks. This also includes setting up such marks by a group that
1443 * was initialized by an unprivileged user.
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001444 */
1445 ret = -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001446 if ((!capable(CAP_SYS_ADMIN) ||
1447 FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001448 mark_type != FAN_MARK_INODE)
1449 goto fput_and_out;
1450
1451 /*
Eric Paris4231a232010-10-28 17:21:56 -04001452 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
1453 * allowed to set permissions events.
1454 */
1455 ret = -EINVAL;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001456 if (mask & FANOTIFY_PERM_EVENTS &&
Eric Paris4231a232010-10-28 17:21:56 -04001457 group->priority == FS_PRIO_0)
1458 goto fput_and_out;
Eric Paris2a3edf82009-12-17 21:24:26 -05001459
Amir Goldstein235328d2019-01-10 19:04:43 +02001460 /*
1461 * Events with data type inode do not carry enough information to report
1462 * event->fd, so we do not allow setting a mask for inode events unless
1463 * group supports reporting fid.
1464 * inode events are not supported on a mount mark, because they do not
1465 * carry enough information (i.e. path) to be filtered by mount point.
1466 */
Amir Goldsteind809daf2020-07-16 11:42:12 +03001467 fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
Amir Goldstein235328d2019-01-10 19:04:43 +02001468 if (mask & FANOTIFY_INODE_EVENTS &&
Amir Goldsteind809daf2020-07-16 11:42:12 +03001469 (!fid_mode || mark_type == FAN_MARK_MOUNT))
Amir Goldstein235328d2019-01-10 19:04:43 +02001470 goto fput_and_out;
1471
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001472 if (flags & FAN_MARK_FLUSH) {
1473 ret = 0;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001474 if (mark_type == FAN_MARK_MOUNT)
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001475 fsnotify_clear_vfsmount_marks_by_group(group);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001476 else if (mark_type == FAN_MARK_FILESYSTEM)
1477 fsnotify_clear_sb_marks_by_group(group);
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001478 else
1479 fsnotify_clear_inode_marks_by_group(group);
1480 goto fput_and_out;
1481 }
1482
Aaron Goidelac5656d2019-08-12 11:20:00 -04001483 ret = fanotify_find_path(dfd, pathname, &path, flags,
1484 (mask & ALL_FSNOTIFY_EVENTS), obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -05001485 if (ret)
1486 goto fput_and_out;
1487
Jan Kara0b3b0942019-05-15 16:28:34 +02001488 if (flags & FAN_MARK_ADD) {
1489 ret = fanotify_events_supported(&path, mask);
1490 if (ret)
1491 goto path_put_and_out;
1492 }
1493
Amir Goldsteind809daf2020-07-16 11:42:12 +03001494 if (fid_mode) {
Gabriel Krisman Bertazi82992122021-10-25 16:27:21 -03001495 ret = fanotify_test_fsid(path.dentry, &__fsid);
1496 if (ret)
1497 goto path_put_and_out;
1498
1499 ret = fanotify_test_fid(path.dentry);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001500 if (ret)
1501 goto path_put_and_out;
Amir Goldstein77115222019-01-10 19:04:37 +02001502
Amir Goldstein73072282019-01-10 19:04:39 +02001503 fsid = &__fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001504 }
1505
Eric Paris2a3edf82009-12-17 21:24:26 -05001506 /* inode held in place by reference to path; group by fget on fd */
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001507 if (mark_type == FAN_MARK_INODE)
Eric Paris0ff21db2009-12-17 21:24:29 -05001508 inode = path.dentry->d_inode;
1509 else
1510 mnt = path.mnt;
Eric Paris2a3edf82009-12-17 21:24:26 -05001511
Amir Goldstein85af5d92020-07-16 11:42:15 +03001512 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1513 if (mnt || !S_ISDIR(inode->i_mode)) {
1514 mask &= ~FAN_EVENT_ON_CHILD;
1515 umask = FAN_EVENT_ON_CHILD;
Amir Goldstein51280632020-07-16 11:42:27 +03001516 /*
1517 * If group needs to report parent fid, register for getting
1518 * events with parent/name info for non-directory.
1519 */
1520 if ((fid_mode & FAN_REPORT_DIR_FID) &&
1521 (flags & FAN_MARK_ADD) && !ignored)
1522 mask |= FAN_EVENT_ON_CHILD;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001523 }
1524
Eric Paris2a3edf82009-12-17 21:24:26 -05001525 /* create/update an inode mark */
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001526 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001527 case FAN_MARK_ADD:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001528 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001529 ret = fanotify_add_vfsmount_mark(group, mnt, mask,
1530 flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001531 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001532 ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
1533 flags, fsid);
Eric Paris0ff21db2009-12-17 21:24:29 -05001534 else
Amir Goldstein77115222019-01-10 19:04:37 +02001535 ret = fanotify_add_inode_mark(group, inode, mask,
1536 flags, fsid);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001537 break;
1538 case FAN_MARK_REMOVE:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001539 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001540 ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001541 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001542 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001543 ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001544 flags, umask);
Andreas Gruenbacherf3640192009-12-17 21:24:29 -05001545 else
Amir Goldstein77115222019-01-10 19:04:37 +02001546 ret = fanotify_remove_inode_mark(group, inode, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001547 flags, umask);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001548 break;
1549 default:
1550 ret = -EINVAL;
1551 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001552
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001553path_put_and_out:
Eric Paris2a3edf82009-12-17 21:24:26 -05001554 path_put(&path);
1555fput_and_out:
Al Viro2903ff02012-08-28 12:52:22 -04001556 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -05001557 return ret;
Eric Parisbbaa4162009-12-17 21:24:26 -05001558}
Eric Paris2a3edf82009-12-17 21:24:26 -05001559
Brian Gerst2ca408d2020-11-30 17:30:59 -05001560#ifndef CONFIG_ARCH_SPLIT_ARG64
Dominik Brodowski183caa32018-03-17 15:06:11 +01001561SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags,
1562 __u64, mask, int, dfd,
1563 const char __user *, pathname)
1564{
1565 return do_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
1566}
Brian Gerst2ca408d2020-11-30 17:30:59 -05001567#endif
Dominik Brodowski183caa32018-03-17 15:06:11 +01001568
Brian Gerst2ca408d2020-11-30 17:30:59 -05001569#if defined(CONFIG_ARCH_SPLIT_ARG64) || defined(CONFIG_COMPAT)
1570SYSCALL32_DEFINE6(fanotify_mark,
Al Viro91c2e0b2013-03-05 20:10:59 -05001571 int, fanotify_fd, unsigned int, flags,
Brian Gerst2ca408d2020-11-30 17:30:59 -05001572 SC_ARG64(mask), int, dfd,
Al Viro91c2e0b2013-03-05 20:10:59 -05001573 const char __user *, pathname)
1574{
Brian Gerst2ca408d2020-11-30 17:30:59 -05001575 return do_fanotify_mark(fanotify_fd, flags, SC_VAL64(__u64, mask),
1576 dfd, pathname);
Al Viro91c2e0b2013-03-05 20:10:59 -05001577}
1578#endif
1579
Eric Paris2a3edf82009-12-17 21:24:26 -05001580/*
Justin P. Mattockae0e47f2011-03-01 15:06:02 +01001581 * fanotify_user_setup - Our initialization function. Note that we cannot return
Eric Paris2a3edf82009-12-17 21:24:26 -05001582 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1583 * must result in panic().
1584 */
1585static int __init fanotify_user_setup(void)
1586{
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001587 struct sysinfo si;
1588 int max_marks;
1589
1590 si_meminfo(&si);
1591 /*
1592 * Allow up to 1% of addressable memory to be accounted for per user
1593 * marks limited to the range [8192, 1048576]. mount and sb marks are
1594 * a lot cheaper than inode marks, but there is no reason for a user
1595 * to have many of those, so calculate by the cost of inode marks.
1596 */
1597 max_marks = (((si.totalram - si.totalhigh) / 100) << PAGE_SHIFT) /
1598 INODE_MARK_COST;
1599 max_marks = clamp(max_marks, FANOTIFY_OLD_DEFAULT_MAX_MARKS,
1600 FANOTIFY_DEFAULT_MAX_USER_MARKS);
1601
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001602 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
Matthew Bobrowskiaf579be2021-08-08 15:26:25 +10001603 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 11);
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001604 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
1605
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001606 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
1607 SLAB_PANIC|SLAB_ACCOUNT);
Jan Kara7088f352020-03-24 17:04:20 +01001608 fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
1609 SLAB_PANIC);
1610 fanotify_path_event_cachep = KMEM_CACHE(fanotify_path_event,
1611 SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001612 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) {
1613 fanotify_perm_event_cachep =
Amir Goldstein33913992019-01-10 19:04:32 +02001614 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001615 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001616
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001617 fanotify_max_queued_events = FANOTIFY_DEFAULT_MAX_EVENTS;
1618 init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS] =
1619 FANOTIFY_DEFAULT_MAX_GROUPS;
1620 init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS] = max_marks;
1621
Eric Paris2a3edf82009-12-17 21:24:26 -05001622 return 0;
1623}
1624device_initcall(fanotify_user_setup);