blob: 921ff05e1877257a7356e3c9181ba9bd0d6ae128 [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 Parisff0b16a2009-12-17 21:24:25 -05003#include <linux/fdtable.h>
4#include <linux/fsnotify_backend.h>
5#include <linux/init.h>
Eric Paris9e66e422009-12-17 21:24:34 -05006#include <linux/jiffies.h>
Eric Parisff0b16a2009-12-17 21:24:25 -05007#include <linux/kernel.h> /* UINT_MAX */
Eric Paris1c529062009-12-17 21:24:28 -05008#include <linux/mount.h>
Eric Paris9e66e422009-12-17 21:24:34 -05009#include <linux/sched.h>
Ingo Molnar5b825c32017-02-02 17:54:15 +010010#include <linux/sched/user.h>
Eric W. Biederman7a360942017-09-26 12:45:33 -050011#include <linux/sched/signal.h>
Eric Parisff0b16a2009-12-17 21:24:25 -050012#include <linux/types.h>
Eric Paris9e66e422009-12-17 21:24:34 -050013#include <linux/wait.h>
Steve Grubbde8cd832017-10-02 20:21:39 -040014#include <linux/audit.h>
Shakeel Buttd46eb14b2018-08-17 15:46:39 -070015#include <linux/sched/mm.h>
Amir Goldsteine9e0c892019-01-10 19:04:34 +020016#include <linux/statfs.h>
Eric Parisff0b16a2009-12-17 21:24:25 -050017
Jan Kara7053aee2014-01-21 15:48:14 -080018#include "fanotify.h"
Eric Paris767cd462009-12-17 21:24:25 -050019
Jan Karaafc894c2020-03-24 16:55:37 +010020static bool fanotify_path_equal(struct path *p1, struct path *p2)
21{
22 return p1->mnt == p2->mnt && p1->dentry == p2->dentry;
23}
24
25static inline bool fanotify_fsid_equal(__kernel_fsid_t *fsid1,
26 __kernel_fsid_t *fsid2)
27{
Nathan Chancellor6def1a12020-03-27 10:10:30 -070028 return fsid1->val[0] == fsid2->val[0] && fsid1->val[1] == fsid2->val[1];
Jan Karaafc894c2020-03-24 16:55:37 +010029}
30
31static bool fanotify_fh_equal(struct fanotify_fh *fh1,
Jan Kara7088f352020-03-24 17:04:20 +010032 struct fanotify_fh *fh2)
Jan Karaafc894c2020-03-24 16:55:37 +010033{
34 if (fh1->type != fh2->type || fh1->len != fh2->len)
35 return false;
36
37 /* Do not merge events if we failed to encode fh */
38 if (fh1->type == FILEID_INVALID)
39 return false;
40
41 return !fh1->len ||
42 !memcmp(fanotify_fh_buf(fh1), fanotify_fh_buf(fh2), fh1->len);
43}
44
Jan Kara7088f352020-03-24 17:04:20 +010045static bool fanotify_fid_event_equal(struct fanotify_fid_event *ffe1,
46 struct fanotify_fid_event *ffe2)
47{
48 /* Do not merge fid events without object fh */
49 if (!ffe1->object_fh.len)
50 return false;
51
52 return fanotify_fsid_equal(&ffe1->fsid, &ffe2->fsid) &&
53 fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh);
54}
55
Amir Goldsteincacfb952020-03-19 17:10:21 +020056static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,
57 struct fanotify_name_event *fne2)
58{
59 /*
60 * Do not merge name events without dir fh.
61 * FAN_DIR_MODIFY does not encode object fh, so it may be empty.
62 */
63 if (!fne1->dir_fh.len)
64 return false;
65
66 if (fne1->name_len != fne2->name_len ||
67 !fanotify_fh_equal(&fne1->dir_fh, &fne2->dir_fh))
68 return false;
69
70 return !memcmp(fne1->name, fne2->name, fne1->name_len);
71}
72
Fabian Frederickab3c4da02020-05-12 20:17:15 +020073static bool fanotify_should_merge(struct fsnotify_event *old_fsn,
Jan Kara7053aee2014-01-21 15:48:14 -080074 struct fsnotify_event *new_fsn)
75{
Amir Goldstein33913992019-01-10 19:04:32 +020076 struct fanotify_event *old, *new;
Jan Kara7053aee2014-01-21 15:48:14 -080077
Jan Kara7053aee2014-01-21 15:48:14 -080078 pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
79 old = FANOTIFY_E(old_fsn);
80 new = FANOTIFY_E(new_fsn);
81
Jan Kara7088f352020-03-24 17:04:20 +010082 if (old_fsn->objectid != new_fsn->objectid ||
83 old->type != new->type || old->pid != new->pid)
Amir Goldsteine9e0c892019-01-10 19:04:34 +020084 return false;
85
Jan Kara7088f352020-03-24 17:04:20 +010086 switch (old->type) {
87 case FANOTIFY_EVENT_TYPE_PATH:
Jan Karaafc894c2020-03-24 16:55:37 +010088 return fanotify_path_equal(fanotify_event_path(old),
89 fanotify_event_path(new));
Jan Kara7088f352020-03-24 17:04:20 +010090 case FANOTIFY_EVENT_TYPE_FID:
Amir Goldsteine7fce6d2019-01-10 19:04:44 +020091 /*
92 * We want to merge many dirent events in the same dir (i.e.
93 * creates/unlinks/renames), but we do not want to merge dirent
94 * events referring to subdirs with dirent events referring to
95 * non subdirs, otherwise, user won't be able to tell from a
96 * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+
97 * unlink pair or rmdir+create pair of events.
98 */
Jan Karaafc894c2020-03-24 16:55:37 +010099 if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR))
100 return false;
101
Jan Kara7088f352020-03-24 17:04:20 +0100102 return fanotify_fid_event_equal(FANOTIFY_FE(old),
103 FANOTIFY_FE(new));
Amir Goldsteincacfb952020-03-19 17:10:21 +0200104 case FANOTIFY_EVENT_TYPE_FID_NAME:
105 return fanotify_name_event_equal(FANOTIFY_NE(old),
106 FANOTIFY_NE(new));
Jan Kara7088f352020-03-24 17:04:20 +0100107 default:
108 WARN_ON_ONCE(1);
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200109 }
110
Eric Paris767cd462009-12-17 21:24:25 -0500111 return false;
112}
113
Eric Parisf70ab542010-07-28 10:18:37 -0400114/* and the list better be locked by something too! */
Jan Kara83c0e1b2014-01-28 18:53:22 +0100115static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
Eric Paris767cd462009-12-17 21:24:25 -0500116{
Jan Kara7053aee2014-01-21 15:48:14 -0800117 struct fsnotify_event *test_event;
Amir Goldstein33913992019-01-10 19:04:32 +0200118 struct fanotify_event *new;
Eric Paris767cd462009-12-17 21:24:25 -0500119
120 pr_debug("%s: list=%p event=%p\n", __func__, list, event);
Amir Goldsteina0a92d22019-01-10 19:04:31 +0200121 new = FANOTIFY_E(event);
Eric Paris767cd462009-12-17 21:24:25 -0500122
Jan Kara13116df2014-01-28 18:29:24 +0100123 /*
124 * Don't merge a permission event with any other event so that we know
125 * the event structure we have created in fanotify_handle_event() is the
126 * one we should check for permission response.
127 */
Amir Goldsteina0a92d22019-01-10 19:04:31 +0200128 if (fanotify_is_perm_event(new->mask))
Jan Kara83c0e1b2014-01-28 18:53:22 +0100129 return 0;
Jan Kara13116df2014-01-28 18:29:24 +0100130
Jan Kara7053aee2014-01-21 15:48:14 -0800131 list_for_each_entry_reverse(test_event, list, list) {
Fabian Frederickab3c4da02020-05-12 20:17:15 +0200132 if (fanotify_should_merge(test_event, event)) {
Amir Goldsteina0a92d22019-01-10 19:04:31 +0200133 FANOTIFY_E(test_event)->mask |= new->mask;
Kinglong Mee6c711002017-02-09 20:45:22 +0800134 return 1;
Eric Parisa12a7dd2009-12-17 21:24:25 -0500135 }
136 }
Eric Parisf70ab542010-07-28 10:18:37 -0400137
Kinglong Mee6c711002017-02-09 20:45:22 +0800138 return 0;
Eric Paris767cd462009-12-17 21:24:25 -0500139}
140
Jan Karafabf7f22019-01-08 15:18:02 +0100141/*
142 * Wait for response to permission event. The function also takes care of
143 * freeing the permission event (or offloads that in case the wait is canceled
144 * by a signal). The function returns 0 in case access got allowed by userspace,
145 * -EPERM in case userspace disallowed the access, and -ERESTARTSYS in case
146 * the wait got interrupted by a signal.
147 */
Jan Karaf0834412014-04-03 14:46:33 -0700148static int fanotify_get_response(struct fsnotify_group *group,
Amir Goldstein33913992019-01-10 19:04:32 +0200149 struct fanotify_perm_event *event,
Jan Kara05f0e382016-11-10 17:45:16 +0100150 struct fsnotify_iter_info *iter_info)
Eric Paris9e66e422009-12-17 21:24:34 -0500151{
152 int ret;
153
154 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
155
Jan Karab5190572019-02-21 11:47:23 +0100156 ret = wait_event_killable(group->fanotify_data.access_waitq,
157 event->state == FAN_EVENT_ANSWERED);
Jan Karafabf7f22019-01-08 15:18:02 +0100158 /* Signal pending? */
159 if (ret < 0) {
160 spin_lock(&group->notification_lock);
161 /* Event reported to userspace and no answer yet? */
162 if (event->state == FAN_EVENT_REPORTED) {
163 /* Event will get freed once userspace answers to it */
164 event->state = FAN_EVENT_CANCELED;
165 spin_unlock(&group->notification_lock);
166 return ret;
167 }
168 /* Event not yet reported? Just remove it. */
169 if (event->state == FAN_EVENT_INIT)
170 fsnotify_remove_queued_event(group, &event->fae.fse);
171 /*
172 * Event may be also answered in case signal delivery raced
173 * with wakeup. In that case we have nothing to do besides
174 * freeing the event and reporting error.
175 */
176 spin_unlock(&group->notification_lock);
177 goto out;
178 }
Eric Paris9e66e422009-12-17 21:24:34 -0500179
180 /* userspace responded, convert to something usable */
Steve Grubbde8cd832017-10-02 20:21:39 -0400181 switch (event->response & ~FAN_AUDIT) {
Eric Paris9e66e422009-12-17 21:24:34 -0500182 case FAN_ALLOW:
183 ret = 0;
184 break;
185 case FAN_DENY:
186 default:
187 ret = -EPERM;
188 }
Steve Grubbde8cd832017-10-02 20:21:39 -0400189
190 /* Check if the response should be audited */
191 if (event->response & FAN_AUDIT)
192 audit_fanotify(event->response & ~FAN_AUDIT);
193
Eric Parisb2d87902009-12-17 21:24:34 -0500194 pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
195 group, event, ret);
Jan Karafabf7f22019-01-08 15:18:02 +0100196out:
197 fsnotify_destroy_event(group, &event->fae.fse);
Amir Goldstein83b535d2019-01-10 19:04:42 +0200198
Eric Paris9e66e422009-12-17 21:24:34 -0500199 return ret;
200}
Eric Paris9e66e422009-12-17 21:24:34 -0500201
Matthew Bobrowski2d10b232018-11-08 14:05:49 +1100202/*
203 * This function returns a mask for an event that only contains the flags
204 * that have been specifically requested by the user. Flags that may have
205 * been included within the event mask, but have not been explicitly
206 * requested by the user, will not be present in the returned mask.
207 */
Amir Goldstein83b535d2019-01-10 19:04:42 +0200208static u32 fanotify_group_event_mask(struct fsnotify_group *group,
209 struct fsnotify_iter_info *iter_info,
210 u32 event_mask, const void *data,
211 int data_type)
Eric Paris1c529062009-12-17 21:24:28 -0500212{
Amir Goldstein54a307b2018-04-04 23:42:18 +0300213 __u32 marks_mask = 0, marks_ignored_mask = 0;
Amir Goldsteine7fce6d2019-01-10 19:04:44 +0200214 __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS;
Amir Goldsteinaa93bdc2020-03-19 17:10:12 +0200215 const struct path *path = fsnotify_data_path(data, data_type);
Amir Goldstein837a3932018-04-20 16:10:54 -0700216 struct fsnotify_mark *mark;
217 int type;
Eric Paris1968f5e2010-07-28 10:18:39 -0400218
Amir Goldstein837a3932018-04-20 16:10:54 -0700219 pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
220 __func__, iter_info->report_mask, event_mask, data, data_type);
Eric Paris1968f5e2010-07-28 10:18:39 -0400221
Amir Goldstein83b535d2019-01-10 19:04:42 +0200222 if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
223 /* Do we have path to open a file descriptor? */
Amir Goldsteinaa93bdc2020-03-19 17:10:12 +0200224 if (!path)
Amir Goldstein83b535d2019-01-10 19:04:42 +0200225 return 0;
226 /* Path type events are only relevant for files and dirs */
227 if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
228 return 0;
229 }
Eric Parise1c048b2010-10-28 17:21:58 -0400230
Amir Goldstein837a3932018-04-20 16:10:54 -0700231 fsnotify_foreach_obj_type(type) {
232 if (!fsnotify_iter_should_report_type(iter_info, type))
233 continue;
234 mark = iter_info->marks[type];
Amir Goldstein2f02fd32020-05-24 10:24:41 +0300235
236 /* Apply ignore mask regardless of ISDIR and ON_CHILD flags */
237 marks_ignored_mask |= mark->ignored_mask;
238
Amir Goldstein837a3932018-04-20 16:10:54 -0700239 /*
Amir Goldstein55bf8822020-03-19 17:10:17 +0200240 * If the event is on dir and this mark doesn't care about
241 * events on dir, don't send it!
242 */
243 if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR))
244 continue;
245
246 /*
Amir Goldsteinb469e7e2018-10-30 20:29:53 +0200247 * If the event is for a child and this mark doesn't care about
248 * events on a child, don't send it!
Amir Goldstein837a3932018-04-20 16:10:54 -0700249 */
Amir Goldsteinb469e7e2018-10-30 20:29:53 +0200250 if (event_mask & FS_EVENT_ON_CHILD &&
251 (type != FSNOTIFY_OBJ_TYPE_INODE ||
252 !(mark->mask & FS_EVENT_ON_CHILD)))
Amir Goldstein837a3932018-04-20 16:10:54 -0700253 continue;
Amir Goldstein54a307b2018-04-04 23:42:18 +0300254
Amir Goldstein837a3932018-04-20 16:10:54 -0700255 marks_mask |= mark->mask;
Eric Paris1968f5e2010-07-28 10:18:39 -0400256 }
257
Amir Goldsteine7fce6d2019-01-10 19:04:44 +0200258 test_mask = event_mask & marks_mask & ~marks_ignored_mask;
259
260 /*
Amir Goldstein9e2ba2c2020-03-19 17:10:19 +0200261 * For dirent modification events (create/delete/move) that do not carry
262 * the child entry name information, we report FAN_ONDIR for mkdir/rmdir
263 * so user can differentiate them from creat/unlink.
Amir Goldsteine7fce6d2019-01-10 19:04:44 +0200264 *
265 * For backward compatibility and consistency, do not report FAN_ONDIR
266 * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR
267 * to user in FAN_REPORT_FID mode for all event types.
268 */
269 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
270 /* Do not report FAN_ONDIR without any event */
271 if (!(test_mask & ~FAN_ONDIR))
272 return 0;
273 } else {
274 user_mask &= ~FAN_ONDIR;
275 }
276
Amir Goldsteine7fce6d2019-01-10 19:04:44 +0200277 return test_mask & user_mask;
Eric Paris1c529062009-12-17 21:24:28 -0500278}
279
Jan Karaafc894c2020-03-24 16:55:37 +0100280static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,
281 gfp_t gfp)
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200282{
Jan Karaafc894c2020-03-24 16:55:37 +0100283 int dwords, type, bytes = 0;
284 char *ext_buf = NULL;
285 void *buf = fh->buf;
286 int err;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200287
Amir Goldsteincacfb952020-03-19 17:10:21 +0200288 if (!inode)
289 goto out;
290
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200291 dwords = 0;
292 err = -ENOENT;
Amir Goldstein77115222019-01-10 19:04:37 +0200293 type = exportfs_encode_inode_fh(inode, NULL, &dwords, NULL);
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200294 if (!dwords)
295 goto out_err;
296
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200297 bytes = dwords << 2;
298 if (bytes > FANOTIFY_INLINE_FH_LEN) {
299 /* Treat failure to allocate fh as failure to allocate event */
300 err = -ENOMEM;
Jan Karaafc894c2020-03-24 16:55:37 +0100301 ext_buf = kmalloc(bytes, gfp);
302 if (!ext_buf)
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200303 goto out_err;
Jan Karaafc894c2020-03-24 16:55:37 +0100304
305 *fanotify_fh_ext_buf_ptr(fh) = ext_buf;
306 buf = ext_buf;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200307 }
308
Jan Karaafc894c2020-03-24 16:55:37 +0100309 type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL);
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200310 err = -EINVAL;
311 if (!type || type == FILEID_INVALID || bytes != dwords << 2)
312 goto out_err;
313
Jan Karaafc894c2020-03-24 16:55:37 +0100314 fh->type = type;
315 fh->len = bytes;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200316
Jan Karaafc894c2020-03-24 16:55:37 +0100317 return;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200318
319out_err:
Jan Karaafc894c2020-03-24 16:55:37 +0100320 pr_warn_ratelimited("fanotify: failed to encode fid (type=%d, len=%d, err=%i)\n",
321 type, bytes, err);
322 kfree(ext_buf);
323 *fanotify_fh_ext_buf_ptr(fh) = NULL;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200324out:
Jan Karaafc894c2020-03-24 16:55:37 +0100325 /* Report the event without a file identifier on encode error */
326 fh->type = FILEID_INVALID;
327 fh->len = 0;
Amir Goldsteine9e0c892019-01-10 19:04:34 +0200328}
329
Amir Goldstein83b535d2019-01-10 19:04:42 +0200330/*
331 * The inode to use as identifier when reporting fid depends on the event.
332 * Report the modified directory inode on dirent modification events.
333 * Report the "victim" inode otherwise.
334 * For example:
335 * FS_ATTRIB reports the child inode even if reported on a watched parent.
336 * FS_CREATE reports the modified dir inode and not the created inode.
337 */
338static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask,
339 const void *data, int data_type)
340{
341 if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
342 return to_tell;
Amir Goldsteinaa93bdc2020-03-19 17:10:12 +0200343
Amir Goldsteincbcf47a2020-07-08 14:11:38 +0300344 return fsnotify_data_inode(data, data_type);
Amir Goldstein83b535d2019-01-10 19:04:42 +0200345}
346
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +0300347static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
348 struct inode *inode, u32 mask,
349 const void *data, int data_type,
350 const struct qstr *file_name,
351 __kernel_fsid_t *fsid)
Jan Karaf0834412014-04-03 14:46:33 -0700352{
Amir Goldstein33913992019-01-10 19:04:32 +0200353 struct fanotify_event *event = NULL;
Jan Kara7088f352020-03-24 17:04:20 +0100354 struct fanotify_fid_event *ffe = NULL;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200355 struct fanotify_name_event *fne = NULL;
Shakeel Buttd46eb14b2018-08-17 15:46:39 -0700356 gfp_t gfp = GFP_KERNEL_ACCOUNT;
Amir Goldstein83b535d2019-01-10 19:04:42 +0200357 struct inode *id = fanotify_fid_inode(inode, mask, data, data_type);
Amir Goldsteinaa93bdc2020-03-19 17:10:12 +0200358 const struct path *path = fsnotify_data_path(data, data_type);
Jan Kara1f5eaa92018-02-21 14:10:59 +0100359
360 /*
361 * For queues with unlimited length lost events are not expected and
362 * can possibly have security implications. Avoid losing events when
Shakeel Buttec165452019-07-11 20:55:52 -0700363 * memory is short. For the limited size queues, avoid OOM killer in the
364 * target monitoring memcg as it may have security repercussion.
Jan Kara1f5eaa92018-02-21 14:10:59 +0100365 */
366 if (group->max_events == UINT_MAX)
367 gfp |= __GFP_NOFAIL;
Shakeel Buttec165452019-07-11 20:55:52 -0700368 else
369 gfp |= __GFP_RETRY_MAYFAIL;
Jan Karaf0834412014-04-03 14:46:33 -0700370
Shakeel Buttd46eb14b2018-08-17 15:46:39 -0700371 /* Whoever is interested in the event, pays for the allocation. */
372 memalloc_use_memcg(group->memcg);
373
Miklos Szeredi6685df32017-10-30 21:14:56 +0100374 if (fanotify_is_perm_event(mask)) {
Amir Goldstein33913992019-01-10 19:04:32 +0200375 struct fanotify_perm_event *pevent;
Jan Karaf0834412014-04-03 14:46:33 -0700376
Jan Kara1f5eaa92018-02-21 14:10:59 +0100377 pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp);
Jan Karaf0834412014-04-03 14:46:33 -0700378 if (!pevent)
Shakeel Buttd46eb14b2018-08-17 15:46:39 -0700379 goto out;
Jan Kara7088f352020-03-24 17:04:20 +0100380
Jan Karaf0834412014-04-03 14:46:33 -0700381 event = &pevent->fae;
Jan Kara7088f352020-03-24 17:04:20 +0100382 event->type = FANOTIFY_EVENT_TYPE_PATH_PERM;
Jan Karaf0834412014-04-03 14:46:33 -0700383 pevent->response = 0;
Jan Kara40873282019-01-08 14:02:44 +0100384 pevent->state = FAN_EVENT_INIT;
Jan Karaf0834412014-04-03 14:46:33 -0700385 goto init;
386 }
Jan Kara7088f352020-03-24 17:04:20 +0100387
Amir Goldsteincacfb952020-03-19 17:10:21 +0200388 /*
389 * For FAN_DIR_MODIFY event, we report the fid of the directory and
390 * the name of the modified entry.
391 * Allocate an fanotify_name_event struct and copy the name.
392 */
393 if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) {
394 fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp);
395 if (!fne)
396 goto out;
397
398 event = &fne->fae;
399 event->type = FANOTIFY_EVENT_TYPE_FID_NAME;
400 fne->name_len = file_name->len;
401 strcpy(fne->name, file_name->name);
402 goto init;
403 }
404
Jan Kara7088f352020-03-24 17:04:20 +0100405 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
406 ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp);
407 if (!ffe)
408 goto out;
409
410 event = &ffe->fae;
411 event->type = FANOTIFY_EVENT_TYPE_FID;
412 } else {
413 struct fanotify_path_event *pevent;
414
415 pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp);
416 if (!pevent)
417 goto out;
418
419 event = &pevent->fae;
420 event->type = FANOTIFY_EVENT_TYPE_PATH;
421 }
422
Amir Goldsteincacfb952020-03-19 17:10:21 +0200423init:
Amir Goldsteinf367a622020-03-19 17:10:16 +0200424 /*
425 * Use the victim inode instead of the watching inode as the id for
426 * event queue, so event reported on parent is merged with event
427 * reported on child when both directory and child watches exist.
428 */
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +0300429 fanotify_init_event(event, (unsigned long)id, mask);
Amir Goldsteind0a6a872018-10-04 00:25:38 +0300430 if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
431 event->pid = get_pid(task_pid(current));
432 else
433 event->pid = get_pid(task_tgid(current));
Jan Kara7088f352020-03-24 17:04:20 +0100434
Amir Goldsteincacfb952020-03-19 17:10:21 +0200435 if (fsid && fanotify_event_fsid(event))
436 *fanotify_event_fsid(event) = *fsid;
437
438 if (fanotify_event_object_fh(event))
439 fanotify_encode_fh(fanotify_event_object_fh(event), id, gfp);
440
441 if (fanotify_event_dir_fh(event))
442 fanotify_encode_fh(fanotify_event_dir_fh(event), id, gfp);
443
444 if (fanotify_event_has_path(event)) {
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +0300445 *fanotify_event_path(event) = *path;
446 path_get(path);
Jan Karaf0834412014-04-03 14:46:33 -0700447 }
Shakeel Buttd46eb14b2018-08-17 15:46:39 -0700448out:
449 memalloc_unuse_memcg();
Jan Karaf0834412014-04-03 14:46:33 -0700450 return event;
451}
452
Amir Goldstein77115222019-01-10 19:04:37 +0200453/*
454 * Get cached fsid of the filesystem containing the object from any connector.
455 * All connectors are supposed to have the same fsid, but we do not verify that
456 * here.
457 */
458static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
459{
460 int type;
461 __kernel_fsid_t fsid = {};
462
463 fsnotify_foreach_obj_type(type) {
Jan Karab1da6a52019-04-24 18:39:57 +0200464 struct fsnotify_mark_connector *conn;
465
Amir Goldstein77115222019-01-10 19:04:37 +0200466 if (!fsnotify_iter_should_report_type(iter_info, type))
467 continue;
468
Jan Karab1da6a52019-04-24 18:39:57 +0200469 conn = READ_ONCE(iter_info->marks[type]->connector);
470 /* Mark is just getting destroyed or created? */
471 if (!conn)
472 continue;
Amir Goldsteinc285a2f2019-06-19 13:34:44 +0300473 if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID))
474 continue;
475 /* Pairs with smp_wmb() in fsnotify_add_mark_list() */
476 smp_rmb();
Jan Karab1da6a52019-04-24 18:39:57 +0200477 fsid = conn->fsid;
Amir Goldstein77115222019-01-10 19:04:37 +0200478 if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1]))
479 continue;
480 return fsid;
481 }
482
483 return fsid;
484}
485
Jan Kara7053aee2014-01-21 15:48:14 -0800486static int fanotify_handle_event(struct fsnotify_group *group,
487 struct inode *inode,
Al Viro3cd5eca2016-11-20 20:19:09 -0500488 u32 mask, const void *data, int data_type,
Al Viroe43e9c32019-04-26 13:51:03 -0400489 const struct qstr *file_name, u32 cookie,
Jan Kara9385a842016-11-10 17:51:50 +0100490 struct fsnotify_iter_info *iter_info)
Jan Kara7053aee2014-01-21 15:48:14 -0800491{
492 int ret = 0;
Amir Goldstein33913992019-01-10 19:04:32 +0200493 struct fanotify_event *event;
Jan Kara7053aee2014-01-21 15:48:14 -0800494 struct fsnotify_event *fsn_event;
Amir Goldstein77115222019-01-10 19:04:37 +0200495 __kernel_fsid_t fsid = {};
Jan Kara7053aee2014-01-21 15:48:14 -0800496
497 BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
498 BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
Amir Goldstein235328d2019-01-10 19:04:43 +0200499 BUILD_BUG_ON(FAN_ATTRIB != FS_ATTRIB);
Jan Kara7053aee2014-01-21 15:48:14 -0800500 BUILD_BUG_ON(FAN_CLOSE_NOWRITE != FS_CLOSE_NOWRITE);
501 BUILD_BUG_ON(FAN_CLOSE_WRITE != FS_CLOSE_WRITE);
502 BUILD_BUG_ON(FAN_OPEN != FS_OPEN);
Amir Goldstein235328d2019-01-10 19:04:43 +0200503 BUILD_BUG_ON(FAN_MOVED_TO != FS_MOVED_TO);
504 BUILD_BUG_ON(FAN_MOVED_FROM != FS_MOVED_FROM);
505 BUILD_BUG_ON(FAN_CREATE != FS_CREATE);
506 BUILD_BUG_ON(FAN_DELETE != FS_DELETE);
Amir Goldstein9e2ba2c2020-03-19 17:10:19 +0200507 BUILD_BUG_ON(FAN_DIR_MODIFY != FS_DIR_MODIFY);
Amir Goldstein235328d2019-01-10 19:04:43 +0200508 BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF);
509 BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF);
Jan Kara7053aee2014-01-21 15:48:14 -0800510 BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD);
511 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
512 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
513 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
514 BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
Matthew Bobrowski9b076f12018-11-08 14:07:14 +1100515 BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC);
Matthew Bobrowski66917a32018-11-08 14:12:44 +1100516 BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM);
Jan Kara7053aee2014-01-21 15:48:14 -0800517
Amir Goldsteinf1793692020-05-27 15:54:55 +0300518 BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19);
Amir Goldsteinbdd5a462018-10-04 00:25:37 +0300519
Amir Goldstein83b535d2019-01-10 19:04:42 +0200520 mask = fanotify_group_event_mask(group, iter_info, mask, data,
521 data_type);
Matthew Bobrowski2d10b232018-11-08 14:05:49 +1100522 if (!mask)
Jan Kara83c4c4b2014-01-21 15:48:15 -0800523 return 0;
524
Jan Kara7053aee2014-01-21 15:48:14 -0800525 pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
526 mask);
527
Miklos Szeredi6685df32017-10-30 21:14:56 +0100528 if (fanotify_is_perm_event(mask)) {
Miklos Szeredif37650f2017-10-30 21:14:56 +0100529 /*
530 * fsnotify_prepare_user_wait() fails if we race with mark
531 * deletion. Just let the operation pass in that case.
532 */
533 if (!fsnotify_prepare_user_wait(iter_info))
534 return 0;
535 }
Miklos Szeredif37650f2017-10-30 21:14:56 +0100536
Jan Karab1da6a52019-04-24 18:39:57 +0200537 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
Amir Goldstein77115222019-01-10 19:04:37 +0200538 fsid = fanotify_get_fsid(iter_info);
Jan Karab1da6a52019-04-24 18:39:57 +0200539 /* Racing with mark destruction or creation? */
540 if (!fsid.val[0] && !fsid.val[1])
541 return 0;
542 }
Amir Goldstein77115222019-01-10 19:04:37 +0200543
Amir Goldstein83b535d2019-01-10 19:04:42 +0200544 event = fanotify_alloc_event(group, inode, mask, data, data_type,
Amir Goldsteincacfb952020-03-19 17:10:21 +0200545 file_name, &fsid);
Miklos Szeredif37650f2017-10-30 21:14:56 +0100546 ret = -ENOMEM;
Jan Kara7b1f6412018-02-21 15:07:52 +0100547 if (unlikely(!event)) {
548 /*
549 * We don't queue overflow events for permission events as
550 * there the access is denied and so no event is in fact lost.
551 */
552 if (!fanotify_is_perm_event(mask))
553 fsnotify_queue_overflow(group);
Miklos Szeredif37650f2017-10-30 21:14:56 +0100554 goto finish;
Jan Kara7b1f6412018-02-21 15:07:52 +0100555 }
Jan Kara7053aee2014-01-21 15:48:14 -0800556
557 fsn_event = &event->fse;
Jan Kara8ba8fa912014-08-06 16:03:26 -0700558 ret = fsnotify_add_event(group, fsn_event, fanotify_merge);
Jan Kara83c0e1b2014-01-28 18:53:22 +0100559 if (ret) {
Jan Kara482ef062014-02-21 19:07:54 +0100560 /* Permission events shouldn't be merged */
Amir Goldstein23c9dee2018-10-04 00:25:35 +0300561 BUG_ON(ret == 1 && mask & FANOTIFY_PERM_EVENTS);
Jan Kara7053aee2014-01-21 15:48:14 -0800562 /* Our event wasn't used in the end. Free it. */
563 fsnotify_destroy_event(group, fsn_event);
Jan Kara482ef062014-02-21 19:07:54 +0100564
Miklos Szeredif37650f2017-10-30 21:14:56 +0100565 ret = 0;
Miklos Szeredi6685df32017-10-30 21:14:56 +0100566 } else if (fanotify_is_perm_event(mask)) {
Jan Kara7088f352020-03-24 17:04:20 +0100567 ret = fanotify_get_response(group, FANOTIFY_PERM(event),
Jan Kara05f0e382016-11-10 17:45:16 +0100568 iter_info);
Jan Kara85816792014-01-28 21:38:06 +0100569 }
Miklos Szeredif37650f2017-10-30 21:14:56 +0100570finish:
Miklos Szeredi6685df32017-10-30 21:14:56 +0100571 if (fanotify_is_perm_event(mask))
Miklos Szeredif37650f2017-10-30 21:14:56 +0100572 fsnotify_finish_user_wait(iter_info);
Miklos Szeredi6685df32017-10-30 21:14:56 +0100573
Jan Kara7053aee2014-01-21 15:48:14 -0800574 return ret;
575}
576
Eric Paris4afeff82010-10-28 17:21:58 -0400577static void fanotify_free_group_priv(struct fsnotify_group *group)
578{
579 struct user_struct *user;
580
581 user = group->fanotify_data.user;
582 atomic_dec(&user->fanotify_listeners);
583 free_uid(user);
584}
585
Jan Kara7088f352020-03-24 17:04:20 +0100586static void fanotify_free_path_event(struct fanotify_event *event)
587{
588 path_put(fanotify_event_path(event));
589 kmem_cache_free(fanotify_path_event_cachep, FANOTIFY_PE(event));
590}
591
592static void fanotify_free_perm_event(struct fanotify_event *event)
593{
594 path_put(fanotify_event_path(event));
595 kmem_cache_free(fanotify_perm_event_cachep, FANOTIFY_PERM(event));
596}
597
598static void fanotify_free_fid_event(struct fanotify_event *event)
599{
600 struct fanotify_fid_event *ffe = FANOTIFY_FE(event);
601
602 if (fanotify_fh_has_ext_buf(&ffe->object_fh))
603 kfree(fanotify_fh_ext_buf(&ffe->object_fh));
604 kmem_cache_free(fanotify_fid_event_cachep, ffe);
605}
606
Amir Goldsteincacfb952020-03-19 17:10:21 +0200607static void fanotify_free_name_event(struct fanotify_event *event)
608{
609 struct fanotify_name_event *fne = FANOTIFY_NE(event);
610
611 if (fanotify_fh_has_ext_buf(&fne->dir_fh))
612 kfree(fanotify_fh_ext_buf(&fne->dir_fh));
613 kfree(fne);
614}
615
Jan Kara7053aee2014-01-21 15:48:14 -0800616static void fanotify_free_event(struct fsnotify_event *fsn_event)
617{
Amir Goldstein33913992019-01-10 19:04:32 +0200618 struct fanotify_event *event;
Jan Kara7053aee2014-01-21 15:48:14 -0800619
620 event = FANOTIFY_E(fsn_event);
Amir Goldsteind0a6a872018-10-04 00:25:38 +0300621 put_pid(event->pid);
Jan Kara7088f352020-03-24 17:04:20 +0100622 switch (event->type) {
623 case FANOTIFY_EVENT_TYPE_PATH:
624 fanotify_free_path_event(event);
625 break;
626 case FANOTIFY_EVENT_TYPE_PATH_PERM:
627 fanotify_free_perm_event(event);
628 break;
629 case FANOTIFY_EVENT_TYPE_FID:
630 fanotify_free_fid_event(event);
631 break;
Amir Goldsteincacfb952020-03-19 17:10:21 +0200632 case FANOTIFY_EVENT_TYPE_FID_NAME:
633 fanotify_free_name_event(event);
634 break;
Amir Goldsteinb8a6c3a2020-07-08 14:11:42 +0300635 case FANOTIFY_EVENT_TYPE_OVERFLOW:
636 kfree(event);
637 break;
Jan Kara7088f352020-03-24 17:04:20 +0100638 default:
639 WARN_ON_ONCE(1);
Jan Karaf0834412014-04-03 14:46:33 -0700640 }
Jan Kara7053aee2014-01-21 15:48:14 -0800641}
642
Jan Kara054c6362016-12-21 18:06:12 +0100643static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
644{
645 kmem_cache_free(fanotify_mark_cache, fsn_mark);
646}
647
Eric Parisff0b16a2009-12-17 21:24:25 -0500648const struct fsnotify_ops fanotify_fsnotify_ops = {
649 .handle_event = fanotify_handle_event,
Eric Paris4afeff82010-10-28 17:21:58 -0400650 .free_group_priv = fanotify_free_group_priv,
Jan Kara7053aee2014-01-21 15:48:14 -0800651 .free_event = fanotify_free_event,
Jan Kara054c6362016-12-21 18:06:12 +0100652 .free_mark = fanotify_free_mark,
Eric Parisff0b16a2009-12-17 21:24:25 -0500653};