blob: 182fea25537672b1b6c41d8aa9da36d60bdd14e4 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -05002#include <linux/fanotify.h>
Eric Paris11637e42009-12-17 21:24:25 -05003#include <linux/fcntl.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05004#include <linux/file.h>
Eric Paris11637e42009-12-17 21:24:25 -05005#include <linux/fs.h>
Eric Paris52c923d2009-12-17 21:24:26 -05006#include <linux/anon_inodes.h>
Eric Paris11637e42009-12-17 21:24:25 -05007#include <linux/fsnotify_backend.h>
Eric Paris2a3edf82009-12-17 21:24:26 -05008#include <linux/init.h>
Eric Parisa1014f12009-12-17 21:24:26 -05009#include <linux/mount.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050010#include <linux/namei.h>
Eric Parisa1014f12009-12-17 21:24:26 -050011#include <linux/poll.h>
Eric Paris11637e42009-12-17 21:24:25 -050012#include <linux/security.h>
13#include <linux/syscalls.h>
Tejun Heoe4e047a2010-05-20 01:36:28 +100014#include <linux/slab.h>
Eric Paris2a3edf82009-12-17 21:24:26 -050015#include <linux/types.h>
Eric Parisa1014f12009-12-17 21:24:26 -050016#include <linux/uaccess.h>
Al Viro91c2e0b2013-03-05 20:10:59 -050017#include <linux/compat.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010018#include <linux/sched/signal.h>
Shakeel Buttd46eb14b2018-08-17 15:46:39 -070019#include <linux/memcontrol.h>
Amir Goldsteina8b13aa2019-01-10 19:04:36 +020020#include <linux/statfs.h>
21#include <linux/exportfs.h>
Eric Parisa1014f12009-12-17 21:24:26 -050022
23#include <asm/ioctls.h>
Eric Paris11637e42009-12-17 21:24:25 -050024
Al Viroc63181e2011-11-25 02:35:16 -050025#include "../../mount.h"
Cyrill Gorcunovbe771962012-12-17 16:05:12 -080026#include "../fdinfo.h"
Jan Kara7053aee2014-01-21 15:48:14 -080027#include "fanotify.h"
Al Viroc63181e2011-11-25 02:35:16 -050028
Eric Paris2529a0d2010-10-28 17:21:57 -040029#define FANOTIFY_DEFAULT_MAX_EVENTS 16384
Amir Goldstein5b8fea62021-03-04 13:29:20 +020030#define FANOTIFY_OLD_DEFAULT_MAX_MARKS 8192
31#define FANOTIFY_DEFAULT_MAX_GROUPS 128
32
33/*
34 * Legacy fanotify marks limits (8192) is per group and we introduced a tunable
35 * limit of marks per user, similar to inotify. Effectively, the legacy limit
36 * of fanotify marks per user is <max marks per group> * <max groups per user>.
37 * This default limit (1M) also happens to match the increased limit of inotify
38 * max_user_watches since v5.10.
39 */
40#define FANOTIFY_DEFAULT_MAX_USER_MARKS \
41 (FANOTIFY_OLD_DEFAULT_MAX_MARKS * FANOTIFY_DEFAULT_MAX_GROUPS)
42
43/*
44 * Most of the memory cost of adding an inode mark is pinning the marked inode.
45 * The size of the filesystem inode struct is not uniform across filesystems,
46 * so double the size of a VFS inode is used as a conservative approximation.
47 */
48#define INODE_MARK_COST (2 * sizeof(struct inode))
49
50/* configurable via /proc/sys/fs/fanotify/ */
51static int fanotify_max_queued_events __read_mostly;
52
53#ifdef CONFIG_SYSCTL
54
55#include <linux/sysctl.h>
56
57struct ctl_table fanotify_table[] = {
58 {
59 .procname = "max_user_groups",
60 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS],
61 .maxlen = sizeof(int),
62 .mode = 0644,
63 .proc_handler = proc_dointvec_minmax,
64 .extra1 = SYSCTL_ZERO,
65 },
66 {
67 .procname = "max_user_marks",
68 .data = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS],
69 .maxlen = sizeof(int),
70 .mode = 0644,
71 .proc_handler = proc_dointvec_minmax,
72 .extra1 = SYSCTL_ZERO,
73 },
74 {
75 .procname = "max_queued_events",
76 .data = &fanotify_max_queued_events,
77 .maxlen = sizeof(int),
78 .mode = 0644,
79 .proc_handler = proc_dointvec_minmax,
80 .extra1 = SYSCTL_ZERO
81 },
82 { }
83};
84#endif /* CONFIG_SYSCTL */
Eric Paris2529a0d2010-10-28 17:21:57 -040085
Heinrich Schuchardt48149e92014-06-04 16:05:44 -070086/*
87 * All flags that may be specified in parameter event_f_flags of fanotify_init.
88 *
89 * Internal and external open flags are stored together in field f_flags of
90 * struct file. Only external open flags shall be allowed in event_f_flags.
91 * Internal flags like FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME shall be
92 * excluded.
93 */
94#define FANOTIFY_INIT_ALL_EVENT_F_BITS ( \
95 O_ACCMODE | O_APPEND | O_NONBLOCK | \
96 __O_SYNC | O_DSYNC | O_CLOEXEC | \
97 O_LARGEFILE | O_NOATIME )
98
Andreas Gruenbacher33d3dff2009-12-17 21:24:29 -050099extern const struct fsnotify_ops fanotify_fsnotify_ops;
Eric Paris11637e42009-12-17 21:24:25 -0500100
Jan Kara054c6362016-12-21 18:06:12 +0100101struct kmem_cache *fanotify_mark_cache __read_mostly;
Jan Kara7088f352020-03-24 17:04:20 +0100102struct kmem_cache *fanotify_fid_event_cachep __read_mostly;
103struct kmem_cache *fanotify_path_event_cachep __read_mostly;
Jan Karaf0834412014-04-03 14:46:33 -0700104struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
Eric Paris2a3edf82009-12-17 21:24:26 -0500105
Amir Goldstein5e469c82019-01-10 19:04:35 +0200106#define FANOTIFY_EVENT_ALIGN 4
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000107#define FANOTIFY_FID_INFO_HDR_LEN \
Amir Goldstein44d705b2020-03-19 17:10:22 +0200108 (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200109
Amir Goldstein44d705b2020-03-19 17:10:22 +0200110static int fanotify_fid_info_len(int fh_len, int name_len)
Amir Goldsteind766b552020-03-19 17:10:20 +0200111{
Amir Goldstein44d705b2020-03-19 17:10:22 +0200112 int info_len = fh_len;
113
114 if (name_len)
115 info_len += name_len + 1;
116
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000117 return roundup(FANOTIFY_FID_INFO_HDR_LEN + info_len,
118 FANOTIFY_EVENT_ALIGN);
Amir Goldsteind766b552020-03-19 17:10:20 +0200119}
120
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000121static int fanotify_event_info_len(unsigned int info_mode,
Amir Goldstein929943b2020-07-16 11:42:28 +0300122 struct fanotify_event *event)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200123{
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300124 struct fanotify_info *info = fanotify_event_info(event);
125 int dir_fh_len = fanotify_event_dir_fh_len(event);
Jan Karaafc894c2020-03-24 16:55:37 +0100126 int fh_len = fanotify_event_object_fh_len(event);
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300127 int info_len = 0;
Amir Goldstein929943b2020-07-16 11:42:28 +0300128 int dot_len = 0;
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300129
Amir Goldstein929943b2020-07-16 11:42:28 +0300130 if (dir_fh_len) {
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300131 info_len += fanotify_fid_info_len(dir_fh_len, info->name_len);
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000132 } else if ((info_mode & FAN_REPORT_NAME) &&
133 (event->mask & FAN_ONDIR)) {
Amir Goldstein929943b2020-07-16 11:42:28 +0300134 /*
135 * With group flag FAN_REPORT_NAME, if name was not recorded in
136 * event on a directory, we will report the name ".".
137 */
138 dot_len = 1;
139 }
Jan Karaafc894c2020-03-24 16:55:37 +0100140
Amir Goldstein44d705b2020-03-19 17:10:22 +0200141 if (fh_len)
Amir Goldstein929943b2020-07-16 11:42:28 +0300142 info_len += fanotify_fid_info_len(fh_len, dot_len);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200143
Amir Goldstein44d705b2020-03-19 17:10:22 +0200144 return info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200145}
146
Eric Parisa1014f12009-12-17 21:24:26 -0500147/*
Amir Goldstein94e00d22021-03-04 12:48:25 +0200148 * Remove an hashed event from merge hash table.
149 */
150static void fanotify_unhash_event(struct fsnotify_group *group,
151 struct fanotify_event *event)
152{
153 assert_spin_locked(&group->notification_lock);
154
155 pr_debug("%s: group=%p event=%p bucket=%u\n", __func__,
156 group, event, fanotify_event_hash_bucket(group, event));
157
158 if (WARN_ON_ONCE(hlist_unhashed(&event->merge_list)))
159 return;
160
161 hlist_del_init(&event->merge_list);
162}
163
164/*
Jan Kara7088f352020-03-24 17:04:20 +0100165 * Get an fanotify notification event if one exists and is small
Eric Parisa1014f12009-12-17 21:24:26 -0500166 * enough to fit in "count". Return an error pointer if the count
Jan Kara40873282019-01-08 14:02:44 +0100167 * is not large enough. When permission event is dequeued, its state is
168 * updated accordingly.
Eric Parisa1014f12009-12-17 21:24:26 -0500169 */
Jan Kara7088f352020-03-24 17:04:20 +0100170static struct fanotify_event *get_one_event(struct fsnotify_group *group,
Eric Parisa1014f12009-12-17 21:24:26 -0500171 size_t count)
172{
Amir Goldstein5e469c82019-01-10 19:04:35 +0200173 size_t event_size = FAN_EVENT_METADATA_LEN;
Jan Kara7088f352020-03-24 17:04:20 +0100174 struct fanotify_event *event = NULL;
Amir Goldstein6f731712021-03-04 12:48:22 +0200175 struct fsnotify_event *fsn_event;
Amir Goldstein929943b2020-07-16 11:42:28 +0300176 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
Eric Parisa1014f12009-12-17 21:24:26 -0500177
178 pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
179
Jan Kara8c554462019-01-08 13:52:31 +0100180 spin_lock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200181 fsn_event = fsnotify_peek_first_event(group);
182 if (!fsn_event)
Jan Kara8c554462019-01-08 13:52:31 +0100183 goto out;
Eric Parisa1014f12009-12-17 21:24:26 -0500184
Amir Goldstein6f731712021-03-04 12:48:22 +0200185 event = FANOTIFY_E(fsn_event);
186 if (fid_mode)
187 event_size += fanotify_event_info_len(fid_mode, event);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200188
Jan Kara8c554462019-01-08 13:52:31 +0100189 if (event_size > count) {
Jan Kara7088f352020-03-24 17:04:20 +0100190 event = ERR_PTR(-EINVAL);
Jan Kara8c554462019-01-08 13:52:31 +0100191 goto out;
192 }
Amir Goldstein6f731712021-03-04 12:48:22 +0200193
194 /*
195 * Held the notification_lock the whole time, so this is the
196 * same event we peeked above.
197 */
198 fsnotify_remove_first_event(group);
Jan Kara7088f352020-03-24 17:04:20 +0100199 if (fanotify_is_perm_event(event->mask))
200 FANOTIFY_PERM(event)->state = FAN_EVENT_REPORTED;
Amir Goldstein94e00d22021-03-04 12:48:25 +0200201 if (fanotify_is_hashed_event(event->mask))
202 fanotify_unhash_event(group, event);
Jan Kara8c554462019-01-08 13:52:31 +0100203out:
204 spin_unlock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100205 return event;
Eric Parisa1014f12009-12-17 21:24:26 -0500206}
207
Jan Karaa741c2f2020-03-24 15:27:52 +0100208static int create_fd(struct fsnotify_group *group, struct path *path,
Jan Kara7053aee2014-01-21 15:48:14 -0800209 struct file **file)
Eric Parisa1014f12009-12-17 21:24:26 -0500210{
211 int client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500212 struct file *new_file;
213
Yann Droneaud0b37e092014-10-09 15:24:40 -0700214 client_fd = get_unused_fd_flags(group->fanotify_data.f_flags);
Eric Parisa1014f12009-12-17 21:24:26 -0500215 if (client_fd < 0)
216 return client_fd;
217
Eric Parisa1014f12009-12-17 21:24:26 -0500218 /*
219 * we need a new file handle for the userspace program so it can read even if it was
220 * originally opened O_WRONLY.
221 */
Jan Karaa741c2f2020-03-24 15:27:52 +0100222 new_file = dentry_open(path,
223 group->fanotify_data.f_flags | FMODE_NONOTIFY,
224 current_cred());
Eric Parisa1014f12009-12-17 21:24:26 -0500225 if (IS_ERR(new_file)) {
226 /*
227 * we still send an event even if we can't open the file. this
228 * can happen when say tasks are gone and we try to open their
229 * /proc files or we try to open a WRONLY file like in sysfs
230 * we just send the errno to userspace since there isn't much
231 * else we can do.
232 */
233 put_unused_fd(client_fd);
234 client_fd = PTR_ERR(new_file);
235 } else {
Al Viro352e3b22012-08-19 12:30:45 -0400236 *file = new_file;
Eric Parisa1014f12009-12-17 21:24:26 -0500237 }
238
Andreas Gruenbacher22aa4252009-12-17 21:24:26 -0500239 return client_fd;
Eric Parisa1014f12009-12-17 21:24:26 -0500240}
241
Jan Kara40873282019-01-08 14:02:44 +0100242/*
243 * Finish processing of permission event by setting it to ANSWERED state and
244 * drop group->notification_lock.
245 */
246static void finish_permission_event(struct fsnotify_group *group,
247 struct fanotify_perm_event *event,
248 unsigned int response)
249 __releases(&group->notification_lock)
250{
Jan Karafabf7f22019-01-08 15:18:02 +0100251 bool destroy = false;
252
Jan Kara40873282019-01-08 14:02:44 +0100253 assert_spin_locked(&group->notification_lock);
254 event->response = response;
Jan Karafabf7f22019-01-08 15:18:02 +0100255 if (event->state == FAN_EVENT_CANCELED)
256 destroy = true;
257 else
258 event->state = FAN_EVENT_ANSWERED;
Jan Kara40873282019-01-08 14:02:44 +0100259 spin_unlock(&group->notification_lock);
Jan Karafabf7f22019-01-08 15:18:02 +0100260 if (destroy)
261 fsnotify_destroy_event(group, &event->fae.fse);
Jan Kara40873282019-01-08 14:02:44 +0100262}
263
Eric Parisb2d87902009-12-17 21:24:34 -0500264static int process_access_response(struct fsnotify_group *group,
265 struct fanotify_response *response_struct)
266{
Amir Goldstein33913992019-01-10 19:04:32 +0200267 struct fanotify_perm_event *event;
Jan Karaf0834412014-04-03 14:46:33 -0700268 int fd = response_struct->fd;
269 int response = response_struct->response;
Eric Parisb2d87902009-12-17 21:24:34 -0500270
271 pr_debug("%s: group=%p fd=%d response=%d\n", __func__, group,
272 fd, response);
273 /*
274 * make sure the response is valid, if invalid we do nothing and either
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300275 * userspace can send a valid response or we will clean it up after the
Eric Parisb2d87902009-12-17 21:24:34 -0500276 * timeout
277 */
Steve Grubbde8cd832017-10-02 20:21:39 -0400278 switch (response & ~FAN_AUDIT) {
Eric Parisb2d87902009-12-17 21:24:34 -0500279 case FAN_ALLOW:
280 case FAN_DENY:
281 break;
282 default:
283 return -EINVAL;
284 }
285
286 if (fd < 0)
287 return -EINVAL;
288
Amir Goldstein96a71f22018-09-21 21:20:30 +0300289 if ((response & FAN_AUDIT) && !FAN_GROUP_FLAG(group, FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -0400290 return -EINVAL;
291
Jan Karaaf6a5112019-01-08 13:28:18 +0100292 spin_lock(&group->notification_lock);
293 list_for_each_entry(event, &group->fanotify_data.access_list,
294 fae.fse.list) {
295 if (event->fd != fd)
296 continue;
Eric Parisb2d87902009-12-17 21:24:34 -0500297
Jan Karaaf6a5112019-01-08 13:28:18 +0100298 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100299 finish_permission_event(group, event, response);
Jan Karaaf6a5112019-01-08 13:28:18 +0100300 wake_up(&group->fanotify_data.access_waitq);
301 return 0;
302 }
303 spin_unlock(&group->notification_lock);
Eric Parisb2d87902009-12-17 21:24:34 -0500304
Jan Karaaf6a5112019-01-08 13:28:18 +0100305 return -ENOENT;
Eric Parisb2d87902009-12-17 21:24:34 -0500306}
Eric Parisb2d87902009-12-17 21:24:34 -0500307
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000308static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,
309 int info_type, const char *name,
310 size_t name_len,
311 char __user *buf, size_t count)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200312{
313 struct fanotify_event_info_fid info = { };
314 struct file_handle handle = { };
Jan Karaafc894c2020-03-24 16:55:37 +0100315 unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200316 size_t fh_len = fh ? fh->len : 0;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200317 size_t info_len = fanotify_fid_info_len(fh_len, name_len);
318 size_t len = info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200319
Amir Goldstein44d705b2020-03-19 17:10:22 +0200320 pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n",
321 __func__, fh_len, name_len, info_len, count);
322
Amir Goldstein83b7a592020-07-16 11:42:26 +0300323 if (!fh_len)
Amir Goldstein5e469c82019-01-10 19:04:35 +0200324 return 0;
325
Amir Goldstein44d705b2020-03-19 17:10:22 +0200326 if (WARN_ON_ONCE(len < sizeof(info) || len > count))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200327 return -EFAULT;
328
Amir Goldstein44d705b2020-03-19 17:10:22 +0200329 /*
330 * Copy event info fid header followed by variable sized file handle
331 * and optionally followed by variable sized filename.
332 */
Amir Goldstein83b7a592020-07-16 11:42:26 +0300333 switch (info_type) {
334 case FAN_EVENT_INFO_TYPE_FID:
335 case FAN_EVENT_INFO_TYPE_DFID:
336 if (WARN_ON_ONCE(name_len))
337 return -EFAULT;
338 break;
339 case FAN_EVENT_INFO_TYPE_DFID_NAME:
340 if (WARN_ON_ONCE(!name || !name_len))
341 return -EFAULT;
342 break;
343 default:
344 return -EFAULT;
345 }
346
347 info.hdr.info_type = info_type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200348 info.hdr.len = len;
Amir Goldsteind766b552020-03-19 17:10:20 +0200349 info.fsid = *fsid;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200350 if (copy_to_user(buf, &info, sizeof(info)))
351 return -EFAULT;
352
353 buf += sizeof(info);
354 len -= sizeof(info);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200355 if (WARN_ON_ONCE(len < sizeof(handle)))
356 return -EFAULT;
357
Jan Karaafc894c2020-03-24 16:55:37 +0100358 handle.handle_type = fh->type;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200359 handle.handle_bytes = fh_len;
360 if (copy_to_user(buf, &handle, sizeof(handle)))
361 return -EFAULT;
362
363 buf += sizeof(handle);
364 len -= sizeof(handle);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200365 if (WARN_ON_ONCE(len < fh_len))
366 return -EFAULT;
367
Jan Karab2d22b62019-03-12 12:42:37 +0100368 /*
Amir Goldstein44d705b2020-03-19 17:10:22 +0200369 * For an inline fh and inline file name, copy through stack to exclude
370 * the copy from usercopy hardening protections.
Jan Karab2d22b62019-03-12 12:42:37 +0100371 */
Jan Karaafc894c2020-03-24 16:55:37 +0100372 fh_buf = fanotify_fh_buf(fh);
Jan Karab2d22b62019-03-12 12:42:37 +0100373 if (fh_len <= FANOTIFY_INLINE_FH_LEN) {
Jan Karaafc894c2020-03-24 16:55:37 +0100374 memcpy(bounce, fh_buf, fh_len);
375 fh_buf = bounce;
Jan Karab2d22b62019-03-12 12:42:37 +0100376 }
Jan Karaafc894c2020-03-24 16:55:37 +0100377 if (copy_to_user(buf, fh_buf, fh_len))
Amir Goldstein5e469c82019-01-10 19:04:35 +0200378 return -EFAULT;
379
Amir Goldstein5e469c82019-01-10 19:04:35 +0200380 buf += fh_len;
381 len -= fh_len;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200382
383 if (name_len) {
384 /* Copy the filename with terminating null */
385 name_len++;
386 if (WARN_ON_ONCE(len < name_len))
387 return -EFAULT;
388
389 if (copy_to_user(buf, name, name_len))
390 return -EFAULT;
391
392 buf += name_len;
393 len -= name_len;
394 }
395
396 /* Pad with 0's */
Amir Goldstein5e469c82019-01-10 19:04:35 +0200397 WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
398 if (len > 0 && clear_user(buf, len))
399 return -EFAULT;
400
Amir Goldstein44d705b2020-03-19 17:10:22 +0200401 return info_len;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200402}
403
Eric Parisa1014f12009-12-17 21:24:26 -0500404static ssize_t copy_event_to_user(struct fsnotify_group *group,
Jan Kara7088f352020-03-24 17:04:20 +0100405 struct fanotify_event *event,
Kees Cook5b03a472018-12-04 15:44:46 -0800406 char __user *buf, size_t count)
Eric Parisa1014f12009-12-17 21:24:26 -0500407{
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200408 struct fanotify_event_metadata metadata;
Jan Kara7088f352020-03-24 17:04:20 +0100409 struct path *path = fanotify_event_path(event);
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300410 struct fanotify_info *info = fanotify_event_info(event);
Amir Goldstein83b7a592020-07-16 11:42:26 +0300411 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200412 struct file *f = NULL;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200413 int ret, fd = FAN_NOFD;
Amir Goldstein83b7a592020-07-16 11:42:26 +0300414 int info_type = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500415
Jan Kara7088f352020-03-24 17:04:20 +0100416 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
Eric Parisa1014f12009-12-17 21:24:26 -0500417
Amir Goldstein44d705b2020-03-19 17:10:22 +0200418 metadata.event_len = FAN_EVENT_METADATA_LEN +
Amir Goldstein929943b2020-07-16 11:42:28 +0300419 fanotify_event_info_len(fid_mode, event);
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200420 metadata.metadata_len = FAN_EVENT_METADATA_LEN;
421 metadata.vers = FANOTIFY_METADATA_VERSION;
422 metadata.reserved = 0;
423 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
424 metadata.pid = pid_vnr(event->pid);
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200425 /*
426 * For an unprivileged listener, event->pid can be used to identify the
427 * events generated by the listener process itself, without disclosing
428 * the pids of other processes.
429 */
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300430 if (FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +0200431 task_tgid(current) != event->pid)
432 metadata.pid = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500433
Amir Goldsteina8b98c82021-05-24 16:53:21 +0300434 /*
435 * For now, fid mode is required for an unprivileged listener and
436 * fid mode does not report fd in events. Keep this check anyway
437 * for safety in case fid mode requirement is relaxed in the future
438 * to allow unprivileged listener to get events with no fd and no fid.
439 */
440 if (!FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
441 path && path->mnt && path->dentry) {
Jan Karaafc894c2020-03-24 16:55:37 +0100442 fd = create_fd(group, path, &f);
443 if (fd < 0)
444 return fd;
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200445 }
446 metadata.fd = fd;
447
Al Viro352e3b22012-08-19 12:30:45 -0400448 ret = -EFAULT;
Kees Cook5b03a472018-12-04 15:44:46 -0800449 /*
450 * Sanity check copy size in case get_one_event() and
Fabian Frederickc5e443c2020-05-12 20:18:36 +0200451 * event_len sizes ever get out of sync.
Kees Cook5b03a472018-12-04 15:44:46 -0800452 */
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200453 if (WARN_ON_ONCE(metadata.event_len > count))
Al Viro352e3b22012-08-19 12:30:45 -0400454 goto out_close_fd;
455
Amir Goldstein5e469c82019-01-10 19:04:35 +0200456 if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN))
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200457 goto out_close_fd;
458
Amir Goldstein44d705b2020-03-19 17:10:22 +0200459 buf += FAN_EVENT_METADATA_LEN;
460 count -= FAN_EVENT_METADATA_LEN;
461
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200462 if (fanotify_is_perm_event(event->mask))
Jan Kara7088f352020-03-24 17:04:20 +0100463 FANOTIFY_PERM(event)->fd = fd;
Eric Parisb2d87902009-12-17 21:24:34 -0500464
Amir Goldstein44d705b2020-03-19 17:10:22 +0200465 if (f)
Al Viro3587b1b2012-11-18 19:19:00 +0000466 fd_install(fd, f);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200467
468 /* Event info records order is: dir fid + name, child fid */
Amir Goldsteinf454fa62020-07-16 11:42:17 +0300469 if (fanotify_event_dir_fh_len(event)) {
Amir Goldstein691d9762020-07-16 11:42:30 +0300470 info_type = info->name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME :
471 FAN_EVENT_INFO_TYPE_DFID;
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000472 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
473 fanotify_info_dir_fh(info),
474 info_type,
475 fanotify_info_name(info),
476 info->name_len, buf, count);
Amir Goldstein5e469c82019-01-10 19:04:35 +0200477 if (ret < 0)
Matthew Bobrowskif644bc42021-06-11 13:32:06 +1000478 goto out_close_fd;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200479
480 buf += ret;
481 count -= ret;
482 }
483
484 if (fanotify_event_object_fh_len(event)) {
Amir Goldstein929943b2020-07-16 11:42:28 +0300485 const char *dot = NULL;
486 int dot_len = 0;
487
Amir Goldstein83b7a592020-07-16 11:42:26 +0300488 if (fid_mode == FAN_REPORT_FID || info_type) {
489 /*
490 * With only group flag FAN_REPORT_FID only type FID is
491 * reported. Second info record type is always FID.
492 */
493 info_type = FAN_EVENT_INFO_TYPE_FID;
Amir Goldstein929943b2020-07-16 11:42:28 +0300494 } else if ((fid_mode & FAN_REPORT_NAME) &&
495 (event->mask & FAN_ONDIR)) {
496 /*
497 * With group flag FAN_REPORT_NAME, if name was not
498 * recorded in an event on a directory, report the
499 * name "." with info type DFID_NAME.
500 */
501 info_type = FAN_EVENT_INFO_TYPE_DFID_NAME;
502 dot = ".";
503 dot_len = 1;
Amir Goldstein83b7a592020-07-16 11:42:26 +0300504 } else if ((event->mask & ALL_FSNOTIFY_DIRENT_EVENTS) ||
505 (event->mask & FAN_ONDIR)) {
506 /*
507 * With group flag FAN_REPORT_DIR_FID, a single info
508 * record has type DFID for directory entry modification
509 * event and for event on a directory.
510 */
511 info_type = FAN_EVENT_INFO_TYPE_DFID;
512 } else {
513 /*
514 * With group flags FAN_REPORT_DIR_FID|FAN_REPORT_FID,
515 * a single info record has type FID for event on a
516 * non-directory, when there is no directory to report.
517 * For example, on FAN_DELETE_SELF event.
518 */
519 info_type = FAN_EVENT_INFO_TYPE_FID;
520 }
521
Matthew Bobrowskid3424c92021-08-08 15:25:32 +1000522 ret = copy_fid_info_to_user(fanotify_event_fsid(event),
523 fanotify_event_object_fh(event),
524 info_type, dot, dot_len,
525 buf, count);
Amir Goldstein44d705b2020-03-19 17:10:22 +0200526 if (ret < 0)
Matthew Bobrowskif644bc42021-06-11 13:32:06 +1000527 goto out_close_fd;
Amir Goldstein44d705b2020-03-19 17:10:22 +0200528
529 buf += ret;
530 count -= ret;
Amir Goldstein5e469c82019-01-10 19:04:35 +0200531 }
532
Amir Goldsteinbb2f7b42019-01-10 19:04:33 +0200533 return metadata.event_len;
Eric Parisb2d87902009-12-17 21:24:34 -0500534
Eric Parisb2d87902009-12-17 21:24:34 -0500535out_close_fd:
Al Viro352e3b22012-08-19 12:30:45 -0400536 if (fd != FAN_NOFD) {
537 put_unused_fd(fd);
538 fput(f);
539 }
Eric Parisb2d87902009-12-17 21:24:34 -0500540 return ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500541}
542
543/* intofiy userspace file descriptor functions */
Al Viro076ccb72017-07-03 01:02:18 -0400544static __poll_t fanotify_poll(struct file *file, poll_table *wait)
Eric Parisa1014f12009-12-17 21:24:26 -0500545{
546 struct fsnotify_group *group = file->private_data;
Al Viro076ccb72017-07-03 01:02:18 -0400547 __poll_t ret = 0;
Eric Parisa1014f12009-12-17 21:24:26 -0500548
549 poll_wait(file, &group->notification_waitq, wait);
Jan Karac21dbe22016-10-07 16:56:52 -0700550 spin_lock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500551 if (!fsnotify_notify_queue_is_empty(group))
Linus Torvaldsa9a08842018-02-11 14:34:03 -0800552 ret = EPOLLIN | EPOLLRDNORM;
Jan Karac21dbe22016-10-07 16:56:52 -0700553 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500554
555 return ret;
556}
557
558static ssize_t fanotify_read(struct file *file, char __user *buf,
559 size_t count, loff_t *pos)
560{
561 struct fsnotify_group *group;
Jan Kara7088f352020-03-24 17:04:20 +0100562 struct fanotify_event *event;
Eric Parisa1014f12009-12-17 21:24:26 -0500563 char __user *start;
564 int ret;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100565 DEFINE_WAIT_FUNC(wait, woken_wake_function);
Eric Parisa1014f12009-12-17 21:24:26 -0500566
567 start = buf;
568 group = file->private_data;
569
570 pr_debug("%s: group=%p\n", __func__, group);
571
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100572 add_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500573 while (1) {
Jan Kara47aaabd2020-07-15 14:06:21 +0200574 /*
575 * User can supply arbitrarily large buffer. Avoid softlockups
576 * in case there are lots of available events.
577 */
578 cond_resched();
Jan Kara7088f352020-03-24 17:04:20 +0100579 event = get_one_event(group, count);
580 if (IS_ERR(event)) {
581 ret = PTR_ERR(event);
Jan Karad8aaab42014-04-03 14:46:35 -0700582 break;
583 }
584
Jan Kara7088f352020-03-24 17:04:20 +0100585 if (!event) {
Jan Karad8aaab42014-04-03 14:46:35 -0700586 ret = -EAGAIN;
587 if (file->f_flags & O_NONBLOCK)
Eric Parisa1014f12009-12-17 21:24:26 -0500588 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700589
590 ret = -ERESTARTSYS;
591 if (signal_pending(current))
Eric Parisa1014f12009-12-17 21:24:26 -0500592 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700593
594 if (start != buf)
595 break;
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100596
597 wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
Eric Parisa1014f12009-12-17 21:24:26 -0500598 continue;
599 }
600
Jan Kara7088f352020-03-24 17:04:20 +0100601 ret = copy_event_to_user(group, event, buf, count);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300602 if (unlikely(ret == -EOPENSTALE)) {
603 /*
604 * We cannot report events with stale fd so drop it.
605 * Setting ret to 0 will continue the event loop and
606 * do the right thing if there are no more events to
607 * read (i.e. return bytes read, -EAGAIN or wait).
608 */
609 ret = 0;
610 }
611
Jan Karad8aaab42014-04-03 14:46:35 -0700612 /*
613 * Permission events get queued to wait for response. Other
614 * events can be destroyed now.
615 */
Jan Kara7088f352020-03-24 17:04:20 +0100616 if (!fanotify_is_perm_event(event->mask)) {
617 fsnotify_destroy_event(group, &event->fse);
Jan Karad5078162014-04-03 14:46:36 -0700618 } else {
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300619 if (ret <= 0) {
Jan Kara40873282019-01-08 14:02:44 +0100620 spin_lock(&group->notification_lock);
621 finish_permission_event(group,
Jan Kara7088f352020-03-24 17:04:20 +0100622 FANOTIFY_PERM(event), FAN_DENY);
Jan Karad5078162014-04-03 14:46:36 -0700623 wake_up(&group->fanotify_data.access_waitq);
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300624 } else {
625 spin_lock(&group->notification_lock);
Jan Kara7088f352020-03-24 17:04:20 +0100626 list_add_tail(&event->fse.list,
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300627 &group->fanotify_data.access_list);
628 spin_unlock(&group->notification_lock);
Jan Karad5078162014-04-03 14:46:36 -0700629 }
Jan Karad5078162014-04-03 14:46:36 -0700630 }
Amir Goldstein4ff33aa2017-04-25 14:29:35 +0300631 if (ret < 0)
632 break;
Jan Karad8aaab42014-04-03 14:46:35 -0700633 buf += ret;
634 count -= ret;
Eric Parisa1014f12009-12-17 21:24:26 -0500635 }
Peter Zijlstra536ebe9ca2014-12-16 16:28:38 +0100636 remove_wait_queue(&group->notification_waitq, &wait);
Eric Parisa1014f12009-12-17 21:24:26 -0500637
Eric Parisa1014f12009-12-17 21:24:26 -0500638 if (start != buf && ret != -EFAULT)
639 ret = buf - start;
640 return ret;
641}
642
Eric Parisb2d87902009-12-17 21:24:34 -0500643static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
644{
Eric Parisb2d87902009-12-17 21:24:34 -0500645 struct fanotify_response response = { .fd = -1, .response = -1 };
646 struct fsnotify_group *group;
647 int ret;
648
Miklos Szeredi6685df32017-10-30 21:14:56 +0100649 if (!IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
650 return -EINVAL;
651
Eric Parisb2d87902009-12-17 21:24:34 -0500652 group = file->private_data;
653
Fabian Frederick5e236632020-05-12 20:19:21 +0200654 if (count < sizeof(response))
655 return -EINVAL;
656
657 count = sizeof(response);
Eric Parisb2d87902009-12-17 21:24:34 -0500658
659 pr_debug("%s: group=%p count=%zu\n", __func__, group, count);
660
661 if (copy_from_user(&response, buf, count))
662 return -EFAULT;
663
664 ret = process_access_response(group, &response);
665 if (ret < 0)
666 count = ret;
667
668 return count;
Eric Parisb2d87902009-12-17 21:24:34 -0500669}
670
Eric Paris52c923d2009-12-17 21:24:26 -0500671static int fanotify_release(struct inode *ignored, struct file *file)
672{
673 struct fsnotify_group *group = file->private_data;
Amir Goldstein6f731712021-03-04 12:48:22 +0200674 struct fsnotify_event *fsn_event;
Andrew Morton19ba54f2010-10-28 17:21:59 -0400675
Jan Kara5838d442014-08-06 16:03:28 -0700676 /*
Jan Kara96d41012016-09-19 14:44:30 -0700677 * Stop new events from arriving in the notification queue. since
678 * userspace cannot use fanotify fd anymore, no event can enter or
679 * leave access_list by now either.
680 */
681 fsnotify_group_stop_queueing(group);
682
683 /*
684 * Process all permission events on access_list and notification queue
685 * and simulate reply from userspace.
Jan Kara5838d442014-08-06 16:03:28 -0700686 */
Jan Kara073f6552016-10-07 16:56:55 -0700687 spin_lock(&group->notification_lock);
Jan Karaca6f8692019-01-09 13:21:01 +0100688 while (!list_empty(&group->fanotify_data.access_list)) {
Jan Kara7088f352020-03-24 17:04:20 +0100689 struct fanotify_perm_event *event;
690
Jan Karaca6f8692019-01-09 13:21:01 +0100691 event = list_first_entry(&group->fanotify_data.access_list,
692 struct fanotify_perm_event, fae.fse.list);
Jan Karaf0834412014-04-03 14:46:33 -0700693 list_del_init(&event->fae.fse.list);
Jan Kara40873282019-01-08 14:02:44 +0100694 finish_permission_event(group, event, FAN_ALLOW);
695 spin_lock(&group->notification_lock);
Eric Paris2eebf582010-08-18 12:25:50 -0400696 }
Eric Paris2eebf582010-08-18 12:25:50 -0400697
Jan Kara5838d442014-08-06 16:03:28 -0700698 /*
Jan Kara96d41012016-09-19 14:44:30 -0700699 * Destroy all non-permission events. For permission events just
700 * dequeue them and set the response. They will be freed once the
701 * response is consumed and fanotify_get_response() returns.
Jan Kara5838d442014-08-06 16:03:28 -0700702 */
Amir Goldstein6f731712021-03-04 12:48:22 +0200703 while ((fsn_event = fsnotify_remove_first_event(group))) {
704 struct fanotify_event *event = FANOTIFY_E(fsn_event);
Jan Kara7088f352020-03-24 17:04:20 +0100705
Jan Kara7088f352020-03-24 17:04:20 +0100706 if (!(event->mask & FANOTIFY_PERM_EVENTS)) {
Jan Karac21dbe22016-10-07 16:56:52 -0700707 spin_unlock(&group->notification_lock);
Amir Goldstein6f731712021-03-04 12:48:22 +0200708 fsnotify_destroy_event(group, fsn_event);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100709 } else {
Jan Kara7088f352020-03-24 17:04:20 +0100710 finish_permission_event(group, FANOTIFY_PERM(event),
Jan Kara40873282019-01-08 14:02:44 +0100711 FAN_ALLOW);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100712 }
Jan Kara40873282019-01-08 14:02:44 +0100713 spin_lock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700714 }
Jan Karac21dbe22016-10-07 16:56:52 -0700715 spin_unlock(&group->notification_lock);
Jan Kara96d41012016-09-19 14:44:30 -0700716
717 /* Response for all permission events it set, wakeup waiters */
Eric Paris2eebf582010-08-18 12:25:50 -0400718 wake_up(&group->fanotify_data.access_waitq);
Eric Paris0a6b6bd2011-10-14 17:43:39 -0400719
Eric Paris52c923d2009-12-17 21:24:26 -0500720 /* matches the fanotify_init->fsnotify_alloc_group */
Lino Sanfilippod8153d42011-06-14 17:29:45 +0200721 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -0500722
723 return 0;
724}
725
Eric Parisa1014f12009-12-17 21:24:26 -0500726static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
727{
728 struct fsnotify_group *group;
Jan Kara7053aee2014-01-21 15:48:14 -0800729 struct fsnotify_event *fsn_event;
Eric Parisa1014f12009-12-17 21:24:26 -0500730 void __user *p;
731 int ret = -ENOTTY;
732 size_t send_len = 0;
733
734 group = file->private_data;
735
736 p = (void __user *) arg;
737
738 switch (cmd) {
739 case FIONREAD:
Jan Karac21dbe22016-10-07 16:56:52 -0700740 spin_lock(&group->notification_lock);
Jan Kara7053aee2014-01-21 15:48:14 -0800741 list_for_each_entry(fsn_event, &group->notification_list, list)
Eric Parisa1014f12009-12-17 21:24:26 -0500742 send_len += FAN_EVENT_METADATA_LEN;
Jan Karac21dbe22016-10-07 16:56:52 -0700743 spin_unlock(&group->notification_lock);
Eric Parisa1014f12009-12-17 21:24:26 -0500744 ret = put_user(send_len, (int __user *) p);
745 break;
746 }
747
748 return ret;
749}
750
Eric Paris52c923d2009-12-17 21:24:26 -0500751static const struct file_operations fanotify_fops = {
Cyrill Gorcunovbe771962012-12-17 16:05:12 -0800752 .show_fdinfo = fanotify_show_fdinfo,
Eric Parisa1014f12009-12-17 21:24:26 -0500753 .poll = fanotify_poll,
754 .read = fanotify_read,
Eric Parisb2d87902009-12-17 21:24:34 -0500755 .write = fanotify_write,
Eric Paris52c923d2009-12-17 21:24:26 -0500756 .fasync = NULL,
757 .release = fanotify_release,
Eric Parisa1014f12009-12-17 21:24:26 -0500758 .unlocked_ioctl = fanotify_ioctl,
Arnd Bergmann1832f2d2018-09-11 21:59:08 +0200759 .compat_ioctl = compat_ptr_ioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200760 .llseek = noop_llseek,
Eric Paris52c923d2009-12-17 21:24:26 -0500761};
762
Eric Paris2a3edf82009-12-17 21:24:26 -0500763static int fanotify_find_path(int dfd, const char __user *filename,
Aaron Goidelac5656d2019-08-12 11:20:00 -0400764 struct path *path, unsigned int flags, __u64 mask,
765 unsigned int obj_type)
Eric Paris2a3edf82009-12-17 21:24:26 -0500766{
767 int ret;
768
769 pr_debug("%s: dfd=%d filename=%p flags=%x\n", __func__,
770 dfd, filename, flags);
771
772 if (filename == NULL) {
Al Viro2903ff02012-08-28 12:52:22 -0400773 struct fd f = fdget(dfd);
Eric Paris2a3edf82009-12-17 21:24:26 -0500774
775 ret = -EBADF;
Al Viro2903ff02012-08-28 12:52:22 -0400776 if (!f.file)
Eric Paris2a3edf82009-12-17 21:24:26 -0500777 goto out;
778
779 ret = -ENOTDIR;
780 if ((flags & FAN_MARK_ONLYDIR) &&
Al Viro496ad9a2013-01-23 17:07:38 -0500781 !(S_ISDIR(file_inode(f.file)->i_mode))) {
Al Viro2903ff02012-08-28 12:52:22 -0400782 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500783 goto out;
784 }
785
Al Viro2903ff02012-08-28 12:52:22 -0400786 *path = f.file->f_path;
Eric Paris2a3edf82009-12-17 21:24:26 -0500787 path_get(path);
Al Viro2903ff02012-08-28 12:52:22 -0400788 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -0500789 } else {
790 unsigned int lookup_flags = 0;
791
792 if (!(flags & FAN_MARK_DONT_FOLLOW))
793 lookup_flags |= LOOKUP_FOLLOW;
794 if (flags & FAN_MARK_ONLYDIR)
795 lookup_flags |= LOOKUP_DIRECTORY;
796
797 ret = user_path_at(dfd, filename, lookup_flags, path);
798 if (ret)
799 goto out;
800 }
801
802 /* you can only watch an inode if you have read permissions on it */
Christian Brauner02f92b32021-01-21 14:19:22 +0100803 ret = path_permission(path, MAY_READ);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400804 if (ret) {
805 path_put(path);
806 goto out;
807 }
808
809 ret = security_path_notify(path, mask, obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -0500810 if (ret)
811 path_put(path);
Aaron Goidelac5656d2019-08-12 11:20:00 -0400812
Eric Paris2a3edf82009-12-17 21:24:26 -0500813out:
814 return ret;
815}
816
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500817static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300818 __u32 mask, unsigned int flags,
819 __u32 umask, int *destroy)
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500820{
Lino Sanfilippod2c18742015-02-10 14:08:24 -0800821 __u32 oldmask = 0;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500822
Amir Goldstein4ed68142020-07-16 11:42:14 +0300823 /* umask bits cannot be removed by user */
824 mask &= ~umask;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500825 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500826 if (!(flags & FAN_MARK_IGNORED_MASK)) {
827 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +0300828 fsn_mark->mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500829 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +0300830 fsn_mark->ignored_mask &= ~mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500831 }
Amir Goldstein4ed68142020-07-16 11:42:14 +0300832 /*
833 * We need to keep the mark around even if remaining mask cannot
834 * result in any events (e.g. mask == FAN_ONDIR) to support incremenal
835 * changes to the mask.
836 * Destroy mark when only umask bits remain.
837 */
838 *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500839 spin_unlock(&fsn_mark->lock);
840
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500841 return mask & oldmask;
842}
843
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300844static int fanotify_remove_mark(struct fsnotify_group *group,
845 fsnotify_connp_t *connp, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300846 unsigned int flags, __u32 umask)
Eric Paris88826272009-12-17 21:24:28 -0500847{
848 struct fsnotify_mark *fsn_mark = NULL;
Andreas Gruenbacher088b09b2009-12-17 21:24:28 -0500849 __u32 removed;
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200850 int destroy_mark;
Eric Paris88826272009-12-17 21:24:28 -0500851
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700852 mutex_lock(&group->mark_mutex);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300853 fsn_mark = fsnotify_find_mark(connp, group);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700854 if (!fsn_mark) {
855 mutex_unlock(&group->mark_mutex);
Eric Paris88826272009-12-17 21:24:28 -0500856 return -ENOENT;
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700857 }
Eric Paris88826272009-12-17 21:24:28 -0500858
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200859 removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300860 umask, &destroy_mark);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +0300861 if (removed & fsnotify_conn_mask(fsn_mark->connector))
862 fsnotify_recalc_mask(fsn_mark->connector);
Lino Sanfilippo6dfbd142011-06-14 17:29:49 +0200863 if (destroy_mark)
Jan Kara4712e7222015-09-04 15:43:12 -0700864 fsnotify_detach_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700865 mutex_unlock(&group->mark_mutex);
Jan Kara4712e7222015-09-04 15:43:12 -0700866 if (destroy_mark)
867 fsnotify_free_mark(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700868
Jan Karab1362ed2016-12-21 16:28:45 +0100869 /* matches the fsnotify_find_mark() */
Eric Paris2a3edf82009-12-17 21:24:26 -0500870 fsnotify_put_mark(fsn_mark);
Eric Paris2a3edf82009-12-17 21:24:26 -0500871 return 0;
872}
873
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300874static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
875 struct vfsmount *mnt, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300876 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300877{
878 return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300879 mask, flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300880}
881
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300882static int fanotify_remove_sb_mark(struct fsnotify_group *group,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300883 struct super_block *sb, __u32 mask,
884 unsigned int flags, __u32 umask)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300885{
Amir Goldstein4ed68142020-07-16 11:42:14 +0300886 return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
887 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300888}
889
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300890static int fanotify_remove_inode_mark(struct fsnotify_group *group,
891 struct inode *inode, __u32 mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300892 unsigned int flags, __u32 umask)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300893{
894 return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
Amir Goldstein4ed68142020-07-16 11:42:14 +0300895 flags, umask);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300896}
897
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500898static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
899 __u32 mask,
900 unsigned int flags)
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500901{
Eric Paris192ca4d2010-10-28 17:21:59 -0400902 __u32 oldmask = -1;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500903
904 spin_lock(&fsn_mark->lock);
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500905 if (!(flags & FAN_MARK_IGNORED_MASK)) {
906 oldmask = fsn_mark->mask;
Amir Goldsteina72fd222018-10-04 00:25:34 +0300907 fsn_mark->mask |= mask;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500908 } else {
Amir Goldsteina72fd222018-10-04 00:25:34 +0300909 fsn_mark->ignored_mask |= mask;
Eric Parisc9778a92009-12-17 21:24:33 -0500910 if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
911 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500912 }
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500913 spin_unlock(&fsn_mark->lock);
914
915 return mask & ~oldmask;
916}
917
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700918static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
Amir Goldsteinb812a9f2018-06-23 17:54:48 +0300919 fsnotify_connp_t *connp,
Amir Goldstein77115222019-01-10 19:04:37 +0200920 unsigned int type,
921 __kernel_fsid_t *fsid)
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700922{
Amir Goldstein5b8fea62021-03-04 13:29:20 +0200923 struct ucounts *ucounts = group->fanotify_data.ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700924 struct fsnotify_mark *mark;
925 int ret;
926
Amir Goldstein5b8fea62021-03-04 13:29:20 +0200927 /*
928 * Enforce per user marks limits per user in all containing user ns.
929 * A group with FAN_UNLIMITED_MARKS does not contribute to mark count
930 * in the limited groups account.
931 */
932 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS) &&
933 !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700934 return ERR_PTR(-ENOSPC);
935
936 mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
Amir Goldstein5b8fea62021-03-04 13:29:20 +0200937 if (!mark) {
938 ret = -ENOMEM;
939 goto out_dec_ucounts;
940 }
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700941
Jan Kara054c6362016-12-21 18:06:12 +0100942 fsnotify_init_mark(mark, group);
Amir Goldstein77115222019-01-10 19:04:37 +0200943 ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700944 if (ret) {
945 fsnotify_put_mark(mark);
Amir Goldstein5b8fea62021-03-04 13:29:20 +0200946 goto out_dec_ucounts;
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700947 }
948
949 return mark;
Amir Goldstein5b8fea62021-03-04 13:29:20 +0200950
951out_dec_ucounts:
952 if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
953 dec_ucount(ucounts, UCOUNT_FANOTIFY_MARKS);
954 return ERR_PTR(ret);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700955}
956
957
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300958static int fanotify_add_mark(struct fsnotify_group *group,
959 fsnotify_connp_t *connp, unsigned int type,
Amir Goldstein77115222019-01-10 19:04:37 +0200960 __u32 mask, unsigned int flags,
961 __kernel_fsid_t *fsid)
Eric Paris2a3edf82009-12-17 21:24:26 -0500962{
963 struct fsnotify_mark *fsn_mark;
Andreas Gruenbacher912ee39462009-12-17 21:24:28 -0500964 __u32 added;
Eric Paris2a3edf82009-12-17 21:24:26 -0500965
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700966 mutex_lock(&group->mark_mutex);
Amir Goldsteinb812a9f2018-06-23 17:54:48 +0300967 fsn_mark = fsnotify_find_mark(connp, group);
Eric Paris88826272009-12-17 21:24:28 -0500968 if (!fsn_mark) {
Amir Goldstein77115222019-01-10 19:04:37 +0200969 fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700970 if (IS_ERR(fsn_mark)) {
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700971 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700972 return PTR_ERR(fsn_mark);
Lino Sanfilippo7b185272013-07-08 15:59:42 -0700973 }
Eric Paris88826272009-12-17 21:24:28 -0500974 }
Eric Parisb9e4e3b2009-12-17 21:24:33 -0500975 added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
Amir Goldstein3ac70bf2018-06-23 17:54:50 +0300976 if (added & ~fsnotify_conn_mask(fsn_mark->connector))
977 fsnotify_recalc_mask(fsn_mark->connector);
Jan Karac9747642016-12-14 13:53:46 +0100978 mutex_unlock(&group->mark_mutex);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700979
Lino Sanfilippofa218ab2010-11-09 18:18:16 +0100980 fsnotify_put_mark(fsn_mark);
Lino Sanfilippo5e9c070c2013-07-08 15:59:43 -0700981 return 0;
Eric Paris88826272009-12-17 21:24:28 -0500982}
983
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300984static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
985 struct vfsmount *mnt, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +0200986 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300987{
988 return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +0200989 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +0300990}
991
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300992static int fanotify_add_sb_mark(struct fsnotify_group *group,
Amir Goldstein77115222019-01-10 19:04:37 +0200993 struct super_block *sb, __u32 mask,
994 unsigned int flags, __kernel_fsid_t *fsid)
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300995{
996 return fanotify_add_mark(group, &sb->s_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +0200997 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +0300998}
999
Andreas Gruenbacher52202df2009-12-17 21:24:28 -05001000static int fanotify_add_inode_mark(struct fsnotify_group *group,
Eric Parisb9e4e3b2009-12-17 21:24:33 -05001001 struct inode *inode, __u32 mask,
Amir Goldstein77115222019-01-10 19:04:37 +02001002 unsigned int flags, __kernel_fsid_t *fsid)
Eric Paris88826272009-12-17 21:24:28 -05001003{
Eric Paris88826272009-12-17 21:24:28 -05001004 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
Eric Paris2a3edf82009-12-17 21:24:26 -05001005
Eric Paris5322a592010-10-28 17:21:57 -04001006 /*
1007 * If some other task has this inode open for write we should not add
1008 * an ignored mark, unless that ignored mark is supposed to survive
1009 * modification changes anyway.
1010 */
1011 if ((flags & FAN_MARK_IGNORED_MASK) &&
1012 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
Nikolay Borisovac9498d2018-12-11 10:27:23 +02001013 inode_is_open_for_write(inode))
Eric Paris5322a592010-10-28 17:21:57 -04001014 return 0;
1015
Amir Goldsteineaa2c6b2018-06-23 17:54:51 +03001016 return fanotify_add_mark(group, &inode->i_fsnotify_marks,
Amir Goldstein77115222019-01-10 19:04:37 +02001017 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
Eric Paris88826272009-12-17 21:24:28 -05001018}
Eric Paris2a3edf82009-12-17 21:24:26 -05001019
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001020static struct fsnotify_event *fanotify_alloc_overflow_event(void)
1021{
1022 struct fanotify_event *oevent;
1023
1024 oevent = kmalloc(sizeof(*oevent), GFP_KERNEL_ACCOUNT);
1025 if (!oevent)
1026 return NULL;
1027
1028 fanotify_init_event(oevent, 0, FS_Q_OVERFLOW);
1029 oevent->type = FANOTIFY_EVENT_TYPE_OVERFLOW;
1030
1031 return &oevent->fse;
1032}
1033
Amir Goldstein94e00d22021-03-04 12:48:25 +02001034static struct hlist_head *fanotify_alloc_merge_hash(void)
1035{
1036 struct hlist_head *hash;
1037
1038 hash = kmalloc(sizeof(struct hlist_head) << FANOTIFY_HTABLE_BITS,
1039 GFP_KERNEL_ACCOUNT);
1040 if (!hash)
1041 return NULL;
1042
1043 __hash_init(hash, FANOTIFY_HTABLE_SIZE);
1044
1045 return hash;
1046}
1047
Eric Paris52c923d2009-12-17 21:24:26 -05001048/* fanotify syscalls */
Eric Paris08ae8932010-05-27 09:41:40 -04001049SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
Eric Paris11637e42009-12-17 21:24:25 -05001050{
Eric Paris52c923d2009-12-17 21:24:26 -05001051 struct fsnotify_group *group;
1052 int f_flags, fd;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001053 unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
1054 unsigned int class = flags & FANOTIFY_CLASS_BITS;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001055 unsigned int internal_flags = 0;
Eric Paris52c923d2009-12-17 21:24:26 -05001056
Amir Goldstein96a71f22018-09-21 21:20:30 +03001057 pr_debug("%s: flags=%x event_f_flags=%x\n",
1058 __func__, flags, event_f_flags);
Eric Paris52c923d2009-12-17 21:24:26 -05001059
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001060 if (!capable(CAP_SYS_ADMIN)) {
1061 /*
1062 * An unprivileged user can setup an fanotify group with
1063 * limited functionality - an unprivileged group is limited to
1064 * notification events with file handles and it cannot use
1065 * unlimited queue/marks.
1066 */
1067 if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode)
1068 return -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001069
1070 /*
1071 * Setting the internal flag FANOTIFY_UNPRIV on the group
1072 * prevents setting mount/filesystem marks on this group and
1073 * prevents reporting pid and open fd in events.
1074 */
1075 internal_flags |= FANOTIFY_UNPRIV;
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001076 }
Eric Paris52c923d2009-12-17 21:24:26 -05001077
Steve Grubbde8cd832017-10-02 20:21:39 -04001078#ifdef CONFIG_AUDITSYSCALL
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001079 if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT))
Steve Grubbde8cd832017-10-02 20:21:39 -04001080#else
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001081 if (flags & ~FANOTIFY_INIT_FLAGS)
Steve Grubbde8cd832017-10-02 20:21:39 -04001082#endif
Eric Paris52c923d2009-12-17 21:24:26 -05001083 return -EINVAL;
1084
Heinrich Schuchardt48149e92014-06-04 16:05:44 -07001085 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS)
1086 return -EINVAL;
1087
1088 switch (event_f_flags & O_ACCMODE) {
1089 case O_RDONLY:
1090 case O_RDWR:
1091 case O_WRONLY:
1092 break;
1093 default:
1094 return -EINVAL;
1095 }
1096
Amir Goldstein83b7a592020-07-16 11:42:26 +03001097 if (fid_mode && class != FAN_CLASS_NOTIF)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001098 return -EINVAL;
1099
Amir Goldstein929943b2020-07-16 11:42:28 +03001100 /*
Amir Goldstein929943b2020-07-16 11:42:28 +03001101 * Child name is reported with parent fid so requires dir fid.
Amir Goldstein691d9762020-07-16 11:42:30 +03001102 * We can report both child fid and dir fid with or without name.
Amir Goldstein929943b2020-07-16 11:42:28 +03001103 */
Amir Goldstein691d9762020-07-16 11:42:30 +03001104 if ((fid_mode & FAN_REPORT_NAME) && !(fid_mode & FAN_REPORT_DIR_FID))
Amir Goldstein83b7a592020-07-16 11:42:26 +03001105 return -EINVAL;
Amir Goldstein83b7a592020-07-16 11:42:26 +03001106
Eric Parisb2d87902009-12-17 21:24:34 -05001107 f_flags = O_RDWR | FMODE_NONOTIFY;
Eric Paris52c923d2009-12-17 21:24:26 -05001108 if (flags & FAN_CLOEXEC)
1109 f_flags |= O_CLOEXEC;
1110 if (flags & FAN_NONBLOCK)
1111 f_flags |= O_NONBLOCK;
1112
1113 /* fsnotify_alloc_group takes a ref. Dropped in fanotify_release */
Shakeel Buttac7b79f2020-12-19 20:46:08 -08001114 group = fsnotify_alloc_user_group(&fanotify_fsnotify_ops);
Eric Paris26379192010-11-23 23:48:26 -05001115 if (IS_ERR(group)) {
Eric Paris52c923d2009-12-17 21:24:26 -05001116 return PTR_ERR(group);
Eric Paris26379192010-11-23 23:48:26 -05001117 }
Eric Paris52c923d2009-12-17 21:24:26 -05001118
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001119 /* Enforce groups limits per user in all containing user ns */
1120 group->fanotify_data.ucounts = inc_ucount(current_user_ns(),
1121 current_euid(),
1122 UCOUNT_FANOTIFY_GROUPS);
1123 if (!group->fanotify_data.ucounts) {
1124 fd = -EMFILE;
1125 goto out_destroy_group;
1126 }
1127
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001128 group->fanotify_data.flags = flags | internal_flags;
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001129 group->memcg = get_mem_cgroup_from_mm(current->mm);
Eric Paris4afeff82010-10-28 17:21:58 -04001130
Amir Goldstein94e00d22021-03-04 12:48:25 +02001131 group->fanotify_data.merge_hash = fanotify_alloc_merge_hash();
1132 if (!group->fanotify_data.merge_hash) {
1133 fd = -ENOMEM;
1134 goto out_destroy_group;
1135 }
1136
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +03001137 group->overflow_event = fanotify_alloc_overflow_event();
1138 if (unlikely(!group->overflow_event)) {
Jan Karaff57cd52014-02-21 19:14:11 +01001139 fd = -ENOMEM;
1140 goto out_destroy_group;
1141 }
Jan Karaff57cd52014-02-21 19:14:11 +01001142
Will Woods1e2ee492014-05-06 12:50:10 -07001143 if (force_o_largefile())
1144 event_f_flags |= O_LARGEFILE;
Eric Paris80af2582010-07-28 10:18:37 -04001145 group->fanotify_data.f_flags = event_f_flags;
Eric Paris9e66e422009-12-17 21:24:34 -05001146 init_waitqueue_head(&group->fanotify_data.access_waitq);
1147 INIT_LIST_HEAD(&group->fanotify_data.access_list);
Amir Goldstein83b7a592020-07-16 11:42:26 +03001148 switch (class) {
Eric Paris4231a232010-10-28 17:21:56 -04001149 case FAN_CLASS_NOTIF:
1150 group->priority = FS_PRIO_0;
1151 break;
1152 case FAN_CLASS_CONTENT:
1153 group->priority = FS_PRIO_1;
1154 break;
1155 case FAN_CLASS_PRE_CONTENT:
1156 group->priority = FS_PRIO_2;
1157 break;
1158 default:
1159 fd = -EINVAL;
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001160 goto out_destroy_group;
Eric Paris4231a232010-10-28 17:21:56 -04001161 }
Eric Pariscb2d4292009-12-17 21:24:34 -05001162
Eric Paris5dd03f52010-10-28 17:21:57 -04001163 if (flags & FAN_UNLIMITED_QUEUE) {
1164 fd = -EPERM;
1165 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001166 goto out_destroy_group;
Eric Paris5dd03f52010-10-28 17:21:57 -04001167 group->max_events = UINT_MAX;
1168 } else {
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001169 group->max_events = fanotify_max_queued_events;
Eric Paris5dd03f52010-10-28 17:21:57 -04001170 }
Eric Paris2529a0d2010-10-28 17:21:57 -04001171
Eric Parisac7e22d2010-10-28 17:21:58 -04001172 if (flags & FAN_UNLIMITED_MARKS) {
1173 fd = -EPERM;
1174 if (!capable(CAP_SYS_ADMIN))
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001175 goto out_destroy_group;
Eric Parisac7e22d2010-10-28 17:21:58 -04001176 }
Eric Parise7099d82010-10-28 17:21:57 -04001177
Steve Grubbde8cd832017-10-02 20:21:39 -04001178 if (flags & FAN_ENABLE_AUDIT) {
1179 fd = -EPERM;
1180 if (!capable(CAP_AUDIT_WRITE))
1181 goto out_destroy_group;
Steve Grubbde8cd832017-10-02 20:21:39 -04001182 }
1183
Eric Paris52c923d2009-12-17 21:24:26 -05001184 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
1185 if (fd < 0)
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001186 goto out_destroy_group;
Eric Paris52c923d2009-12-17 21:24:26 -05001187
1188 return fd;
1189
Lino Sanfilippod8153d42011-06-14 17:29:45 +02001190out_destroy_group:
1191 fsnotify_destroy_group(group);
Eric Paris52c923d2009-12-17 21:24:26 -05001192 return fd;
Eric Paris11637e42009-12-17 21:24:25 -05001193}
Eric Parisbbaa4162009-12-17 21:24:26 -05001194
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001195/* Check if filesystem can encode a unique fid */
Amir Goldstein73072282019-01-10 19:04:39 +02001196static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001197{
Amir Goldstein73072282019-01-10 19:04:39 +02001198 __kernel_fsid_t root_fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001199 int err;
1200
1201 /*
1202 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
1203 */
Amir Goldstein73072282019-01-10 19:04:39 +02001204 err = vfs_get_fsid(path->dentry, fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001205 if (err)
1206 return err;
1207
Amir Goldstein73072282019-01-10 19:04:39 +02001208 if (!fsid->val[0] && !fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001209 return -ENODEV;
1210
1211 /*
1212 * Make sure path is not inside a filesystem subvolume (e.g. btrfs)
1213 * which uses a different fsid than sb root.
1214 */
Amir Goldstein73072282019-01-10 19:04:39 +02001215 err = vfs_get_fsid(path->dentry->d_sb->s_root, &root_fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001216 if (err)
1217 return err;
1218
Amir Goldstein73072282019-01-10 19:04:39 +02001219 if (root_fsid.val[0] != fsid->val[0] ||
1220 root_fsid.val[1] != fsid->val[1])
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001221 return -EXDEV;
1222
1223 /*
1224 * We need to make sure that the file system supports at least
1225 * encoding a file handle so user can use name_to_handle_at() to
1226 * compare fid returned with event to the file handle of watched
1227 * objects. However, name_to_handle_at() requires that the
1228 * filesystem also supports decoding file handles.
1229 */
1230 if (!path->dentry->d_sb->s_export_op ||
1231 !path->dentry->d_sb->s_export_op->fh_to_dentry)
1232 return -EOPNOTSUPP;
1233
1234 return 0;
1235}
1236
Jan Kara0b3b0942019-05-15 16:28:34 +02001237static int fanotify_events_supported(struct path *path, __u64 mask)
1238{
1239 /*
1240 * Some filesystems such as 'proc' acquire unusual locks when opening
1241 * files. For them fanotify permission events have high chances of
1242 * deadlocking the system - open done when reporting fanotify event
1243 * blocks on this "unusual" lock while another process holding the lock
1244 * waits for fanotify permission event to be answered. Just disallow
1245 * permission events for such filesystems.
1246 */
1247 if (mask & FANOTIFY_PERM_EVENTS &&
1248 path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM)
1249 return -EINVAL;
1250 return 0;
1251}
1252
Dominik Brodowski183caa32018-03-17 15:06:11 +01001253static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1254 int dfd, const char __user *pathname)
Eric Parisbbaa4162009-12-17 21:24:26 -05001255{
Eric Paris0ff21db2009-12-17 21:24:29 -05001256 struct inode *inode = NULL;
1257 struct vfsmount *mnt = NULL;
Eric Paris2a3edf82009-12-17 21:24:26 -05001258 struct fsnotify_group *group;
Al Viro2903ff02012-08-28 12:52:22 -04001259 struct fd f;
Eric Paris2a3edf82009-12-17 21:24:26 -05001260 struct path path;
Amir Goldstein73072282019-01-10 19:04:39 +02001261 __kernel_fsid_t __fsid, *fsid = NULL;
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001262 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001263 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
Amir Goldstein3ef86652020-07-16 11:42:13 +03001264 bool ignored = flags & FAN_MARK_IGNORED_MASK;
Amir Goldsteind809daf2020-07-16 11:42:12 +03001265 unsigned int obj_type, fid_mode;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001266 u32 umask = 0;
Al Viro2903ff02012-08-28 12:52:22 -04001267 int ret;
Eric Paris2a3edf82009-12-17 21:24:26 -05001268
1269 pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n",
1270 __func__, fanotify_fd, flags, dfd, pathname, mask);
1271
1272 /* we only use the lower 32 bits as of right now. */
Christian Brauner22d483b2021-03-25 09:37:43 +01001273 if (upper_32_bits(mask))
Eric Paris2a3edf82009-12-17 21:24:26 -05001274 return -EINVAL;
1275
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001276 if (flags & ~FANOTIFY_MARK_FLAGS)
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001277 return -EINVAL;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001278
1279 switch (mark_type) {
1280 case FAN_MARK_INODE:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001281 obj_type = FSNOTIFY_OBJ_TYPE_INODE;
1282 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001283 case FAN_MARK_MOUNT:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001284 obj_type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
1285 break;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001286 case FAN_MARK_FILESYSTEM:
Aaron Goidelac5656d2019-08-12 11:20:00 -04001287 obj_type = FSNOTIFY_OBJ_TYPE_SB;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001288 break;
1289 default:
1290 return -EINVAL;
1291 }
1292
Eric Paris4d926042009-12-17 21:24:34 -05001293 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001294 case FAN_MARK_ADD:
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001295 case FAN_MARK_REMOVE:
Lino Sanfilippo1734dee2010-11-22 18:46:33 +01001296 if (!mask)
1297 return -EINVAL;
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001298 break;
Eric Paris4d926042009-12-17 21:24:34 -05001299 case FAN_MARK_FLUSH:
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001300 if (flags & ~(FANOTIFY_MARK_TYPE_BITS | FAN_MARK_FLUSH))
Heinrich Schuchardtcc299a92014-06-04 16:05:43 -07001301 return -EINVAL;
Andreas Gruenbacher88380fe2009-12-17 21:24:29 -05001302 break;
1303 default:
1304 return -EINVAL;
1305 }
Eric Paris8fcd6522010-10-28 17:21:59 -04001306
Miklos Szeredi6685df32017-10-30 21:14:56 +01001307 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS))
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001308 valid_mask |= FANOTIFY_PERM_EVENTS;
Miklos Szeredi6685df32017-10-30 21:14:56 +01001309
1310 if (mask & ~valid_mask)
Eric Paris2a3edf82009-12-17 21:24:26 -05001311 return -EINVAL;
1312
Amir Goldstein3ef86652020-07-16 11:42:13 +03001313 /* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */
1314 if (ignored)
1315 mask &= ~FANOTIFY_EVENT_FLAGS;
1316
Al Viro2903ff02012-08-28 12:52:22 -04001317 f = fdget(fanotify_fd);
1318 if (unlikely(!f.file))
Eric Paris2a3edf82009-12-17 21:24:26 -05001319 return -EBADF;
1320
1321 /* verify that this is indeed an fanotify instance */
1322 ret = -EINVAL;
Al Viro2903ff02012-08-28 12:52:22 -04001323 if (unlikely(f.file->f_op != &fanotify_fops))
Eric Paris2a3edf82009-12-17 21:24:26 -05001324 goto fput_and_out;
Al Viro2903ff02012-08-28 12:52:22 -04001325 group = f.file->private_data;
Eric Paris4231a232010-10-28 17:21:56 -04001326
1327 /*
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001328 * An unprivileged user is not allowed to setup mount nor filesystem
1329 * marks. This also includes setting up such marks by a group that
1330 * was initialized by an unprivileged user.
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001331 */
1332 ret = -EPERM;
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001333 if ((!capable(CAP_SYS_ADMIN) ||
1334 FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
Amir Goldstein7cea2a32021-03-04 13:29:21 +02001335 mark_type != FAN_MARK_INODE)
1336 goto fput_and_out;
1337
1338 /*
Eric Paris4231a232010-10-28 17:21:56 -04001339 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
1340 * allowed to set permissions events.
1341 */
1342 ret = -EINVAL;
Amir Goldstein23c9dee2018-10-04 00:25:35 +03001343 if (mask & FANOTIFY_PERM_EVENTS &&
Eric Paris4231a232010-10-28 17:21:56 -04001344 group->priority == FS_PRIO_0)
1345 goto fput_and_out;
Eric Paris2a3edf82009-12-17 21:24:26 -05001346
Amir Goldstein235328d2019-01-10 19:04:43 +02001347 /*
1348 * Events with data type inode do not carry enough information to report
1349 * event->fd, so we do not allow setting a mask for inode events unless
1350 * group supports reporting fid.
1351 * inode events are not supported on a mount mark, because they do not
1352 * carry enough information (i.e. path) to be filtered by mount point.
1353 */
Amir Goldsteind809daf2020-07-16 11:42:12 +03001354 fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
Amir Goldstein235328d2019-01-10 19:04:43 +02001355 if (mask & FANOTIFY_INODE_EVENTS &&
Amir Goldsteind809daf2020-07-16 11:42:12 +03001356 (!fid_mode || mark_type == FAN_MARK_MOUNT))
Amir Goldstein235328d2019-01-10 19:04:43 +02001357 goto fput_and_out;
1358
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001359 if (flags & FAN_MARK_FLUSH) {
1360 ret = 0;
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001361 if (mark_type == FAN_MARK_MOUNT)
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001362 fsnotify_clear_vfsmount_marks_by_group(group);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001363 else if (mark_type == FAN_MARK_FILESYSTEM)
1364 fsnotify_clear_sb_marks_by_group(group);
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001365 else
1366 fsnotify_clear_inode_marks_by_group(group);
1367 goto fput_and_out;
1368 }
1369
Aaron Goidelac5656d2019-08-12 11:20:00 -04001370 ret = fanotify_find_path(dfd, pathname, &path, flags,
1371 (mask & ALL_FSNOTIFY_EVENTS), obj_type);
Eric Paris2a3edf82009-12-17 21:24:26 -05001372 if (ret)
1373 goto fput_and_out;
1374
Jan Kara0b3b0942019-05-15 16:28:34 +02001375 if (flags & FAN_MARK_ADD) {
1376 ret = fanotify_events_supported(&path, mask);
1377 if (ret)
1378 goto path_put_and_out;
1379 }
1380
Amir Goldsteind809daf2020-07-16 11:42:12 +03001381 if (fid_mode) {
Amir Goldstein73072282019-01-10 19:04:39 +02001382 ret = fanotify_test_fid(&path, &__fsid);
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001383 if (ret)
1384 goto path_put_and_out;
Amir Goldstein77115222019-01-10 19:04:37 +02001385
Amir Goldstein73072282019-01-10 19:04:39 +02001386 fsid = &__fsid;
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001387 }
1388
Eric Paris2a3edf82009-12-17 21:24:26 -05001389 /* inode held in place by reference to path; group by fget on fd */
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001390 if (mark_type == FAN_MARK_INODE)
Eric Paris0ff21db2009-12-17 21:24:29 -05001391 inode = path.dentry->d_inode;
1392 else
1393 mnt = path.mnt;
Eric Paris2a3edf82009-12-17 21:24:26 -05001394
Amir Goldstein85af5d92020-07-16 11:42:15 +03001395 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1396 if (mnt || !S_ISDIR(inode->i_mode)) {
1397 mask &= ~FAN_EVENT_ON_CHILD;
1398 umask = FAN_EVENT_ON_CHILD;
Amir Goldstein51280632020-07-16 11:42:27 +03001399 /*
1400 * If group needs to report parent fid, register for getting
1401 * events with parent/name info for non-directory.
1402 */
1403 if ((fid_mode & FAN_REPORT_DIR_FID) &&
1404 (flags & FAN_MARK_ADD) && !ignored)
1405 mask |= FAN_EVENT_ON_CHILD;
Amir Goldstein85af5d92020-07-16 11:42:15 +03001406 }
1407
Eric Paris2a3edf82009-12-17 21:24:26 -05001408 /* create/update an inode mark */
Heinrich Schuchardt0a8dd2d2014-06-04 16:05:40 -07001409 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001410 case FAN_MARK_ADD:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001411 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001412 ret = fanotify_add_vfsmount_mark(group, mnt, mask,
1413 flags, fsid);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001414 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001415 ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
1416 flags, fsid);
Eric Paris0ff21db2009-12-17 21:24:29 -05001417 else
Amir Goldstein77115222019-01-10 19:04:37 +02001418 ret = fanotify_add_inode_mark(group, inode, mask,
1419 flags, fsid);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001420 break;
1421 case FAN_MARK_REMOVE:
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001422 if (mark_type == FAN_MARK_MOUNT)
Amir Goldstein77115222019-01-10 19:04:37 +02001423 ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001424 flags, umask);
Amir Goldsteind54f4fb2018-09-01 10:41:13 +03001425 else if (mark_type == FAN_MARK_FILESYSTEM)
Amir Goldstein77115222019-01-10 19:04:37 +02001426 ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001427 flags, umask);
Andreas Gruenbacherf3640192009-12-17 21:24:29 -05001428 else
Amir Goldstein77115222019-01-10 19:04:37 +02001429 ret = fanotify_remove_inode_mark(group, inode, mask,
Amir Goldstein85af5d92020-07-16 11:42:15 +03001430 flags, umask);
Andreas Gruenbacherc6223f42009-12-17 21:24:28 -05001431 break;
1432 default:
1433 ret = -EINVAL;
1434 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001435
Amir Goldsteina8b13aa2019-01-10 19:04:36 +02001436path_put_and_out:
Eric Paris2a3edf82009-12-17 21:24:26 -05001437 path_put(&path);
1438fput_and_out:
Al Viro2903ff02012-08-28 12:52:22 -04001439 fdput(f);
Eric Paris2a3edf82009-12-17 21:24:26 -05001440 return ret;
Eric Parisbbaa4162009-12-17 21:24:26 -05001441}
Eric Paris2a3edf82009-12-17 21:24:26 -05001442
Brian Gerst2ca408d2020-11-30 17:30:59 -05001443#ifndef CONFIG_ARCH_SPLIT_ARG64
Dominik Brodowski183caa32018-03-17 15:06:11 +01001444SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags,
1445 __u64, mask, int, dfd,
1446 const char __user *, pathname)
1447{
1448 return do_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
1449}
Brian Gerst2ca408d2020-11-30 17:30:59 -05001450#endif
Dominik Brodowski183caa32018-03-17 15:06:11 +01001451
Brian Gerst2ca408d2020-11-30 17:30:59 -05001452#if defined(CONFIG_ARCH_SPLIT_ARG64) || defined(CONFIG_COMPAT)
1453SYSCALL32_DEFINE6(fanotify_mark,
Al Viro91c2e0b2013-03-05 20:10:59 -05001454 int, fanotify_fd, unsigned int, flags,
Brian Gerst2ca408d2020-11-30 17:30:59 -05001455 SC_ARG64(mask), int, dfd,
Al Viro91c2e0b2013-03-05 20:10:59 -05001456 const char __user *, pathname)
1457{
Brian Gerst2ca408d2020-11-30 17:30:59 -05001458 return do_fanotify_mark(fanotify_fd, flags, SC_VAL64(__u64, mask),
1459 dfd, pathname);
Al Viro91c2e0b2013-03-05 20:10:59 -05001460}
1461#endif
1462
Eric Paris2a3edf82009-12-17 21:24:26 -05001463/*
Justin P. Mattockae0e47f2011-03-01 15:06:02 +01001464 * fanotify_user_setup - Our initialization function. Note that we cannot return
Eric Paris2a3edf82009-12-17 21:24:26 -05001465 * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1466 * must result in panic().
1467 */
1468static int __init fanotify_user_setup(void)
1469{
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001470 struct sysinfo si;
1471 int max_marks;
1472
1473 si_meminfo(&si);
1474 /*
1475 * Allow up to 1% of addressable memory to be accounted for per user
1476 * marks limited to the range [8192, 1048576]. mount and sb marks are
1477 * a lot cheaper than inode marks, but there is no reason for a user
1478 * to have many of those, so calculate by the cost of inode marks.
1479 */
1480 max_marks = (((si.totalram - si.totalhigh) / 100) << PAGE_SHIFT) /
1481 INODE_MARK_COST;
1482 max_marks = clamp(max_marks, FANOTIFY_OLD_DEFAULT_MAX_MARKS,
1483 FANOTIFY_DEFAULT_MAX_USER_MARKS);
1484
Amir Goldsteina8b98c82021-05-24 16:53:21 +03001485 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
Amir Goldstein929943b2020-07-16 11:42:28 +03001486 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10);
Amir Goldsteinbdd5a462018-10-04 00:25:37 +03001487 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
1488
Shakeel Buttd46eb14b2018-08-17 15:46:39 -07001489 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
1490 SLAB_PANIC|SLAB_ACCOUNT);
Jan Kara7088f352020-03-24 17:04:20 +01001491 fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
1492 SLAB_PANIC);
1493 fanotify_path_event_cachep = KMEM_CACHE(fanotify_path_event,
1494 SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001495 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) {
1496 fanotify_perm_event_cachep =
Amir Goldstein33913992019-01-10 19:04:32 +02001497 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
Miklos Szeredi6685df32017-10-30 21:14:56 +01001498 }
Eric Paris2a3edf82009-12-17 21:24:26 -05001499
Amir Goldstein5b8fea62021-03-04 13:29:20 +02001500 fanotify_max_queued_events = FANOTIFY_DEFAULT_MAX_EVENTS;
1501 init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS] =
1502 FANOTIFY_DEFAULT_MAX_GROUPS;
1503 init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS] = max_marks;
1504
Eric Paris2a3edf82009-12-17 21:24:26 -05001505 return 0;
1506}
1507device_initcall(fanotify_user_setup);