hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/notify/inotify/inotify_fsnotify.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * fs/inotify_user.c - inotify support for userspace
34 *
....@@ -10,16 +11,6 @@
1011 *
1112 * Copyright (C) 2009 Eric Paris <Red Hat Inc>
1213 * inotify was largely rewriten to make use of the fsnotify infrastructure
13
- *
14
- * This program is free software; you can redistribute it and/or modify it
15
- * under the terms of the GNU General Public License as published by the
16
- * Free Software Foundation; either version 2, or (at your option) any
17
- * later version.
18
- *
19
- * This program is distributed in the hope that it will be useful, but
20
- * WITHOUT ANY WARRANTY; without even the implied warranty of
21
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
- * General Public License for more details.
2314 */
2415
2516 #include <linux/dcache.h> /* d_unlinked */
....@@ -43,12 +34,12 @@
4334 {
4435 struct inotify_event_info *old, *new;
4536
46
- if (old_fsn->mask & FS_IN_IGNORED)
47
- return false;
4837 old = INOTIFY_E(old_fsn);
4938 new = INOTIFY_E(new_fsn);
50
- if ((old_fsn->mask == new_fsn->mask) &&
51
- (old_fsn->inode == new_fsn->inode) &&
39
+ if (old->mask & FS_IN_IGNORED)
40
+ return false;
41
+ if ((old->mask == new->mask) &&
42
+ (old->wd == new->wd) &&
5243 (old->name_len == new->name_len) &&
5344 (!old->name_len || !strcmp(old->name, new->name)))
5445 return true;
....@@ -64,49 +55,45 @@
6455 return event_compare(last_event, event);
6556 }
6657
67
-int inotify_handle_event(struct fsnotify_group *group,
68
- struct inode *inode,
69
- u32 mask, const void *data, int data_type,
70
- const unsigned char *file_name, u32 cookie,
71
- struct fsnotify_iter_info *iter_info)
58
+int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
59
+ struct inode *inode, struct inode *dir,
60
+ const struct qstr *name, u32 cookie)
7261 {
73
- struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
7462 struct inotify_inode_mark *i_mark;
7563 struct inotify_event_info *event;
7664 struct fsnotify_event *fsn_event;
65
+ struct fsnotify_group *group = inode_mark->group;
7766 int ret;
78
- int len = 0;
67
+ int len = 0, wd;
7968 int alloc_len = sizeof(struct inotify_event_info);
69
+ struct mem_cgroup *old_memcg;
8070
81
- if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
82
- return 0;
83
-
84
- if ((inode_mark->mask & FS_EXCL_UNLINK) &&
85
- (data_type == FSNOTIFY_EVENT_PATH)) {
86
- const struct path *path = data;
87
-
88
- if (d_unlinked(path->dentry))
89
- return 0;
90
- }
91
- if (file_name) {
92
- len = strlen(file_name);
71
+ if (name) {
72
+ len = name->len;
9373 alloc_len += len + 1;
9474 }
9575
96
- pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
76
+ pr_debug("%s: group=%p mark=%p mask=%x\n", __func__, group, inode_mark,
9777 mask);
9878
9979 i_mark = container_of(inode_mark, struct inotify_inode_mark,
10080 fsn_mark);
10181
10282 /*
83
+ * We can be racing with mark being detached. Don't report event with
84
+ * invalid wd.
85
+ */
86
+ wd = READ_ONCE(i_mark->wd);
87
+ if (wd == -1)
88
+ return 0;
89
+ /*
10390 * Whoever is interested in the event, pays for the allocation. Do not
10491 * trigger OOM killer in the target monitoring memcg as it may have
10592 * security repercussion.
10693 */
107
- memalloc_use_memcg(group->memcg);
94
+ old_memcg = set_active_memcg(group->memcg);
10895 event = kmalloc(alloc_len, GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
109
- memalloc_unuse_memcg();
96
+ set_active_memcg(old_memcg);
11097
11198 if (unlikely(!event)) {
11299 /*
....@@ -117,13 +104,23 @@
117104 return -ENOMEM;
118105 }
119106
107
+ /*
108
+ * We now report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
109
+ * for fanotify. inotify never reported IN_ISDIR with those events.
110
+ * It looks like an oversight, but to avoid the risk of breaking
111
+ * existing inotify programs, mask the flag out from those events.
112
+ */
113
+ if (mask & (IN_MOVE_SELF | IN_DELETE_SELF))
114
+ mask &= ~IN_ISDIR;
115
+
120116 fsn_event = &event->fse;
121
- fsnotify_init_event(fsn_event, inode, mask);
122
- event->wd = i_mark->wd;
117
+ fsnotify_init_event(fsn_event, 0);
118
+ event->mask = mask;
119
+ event->wd = wd;
123120 event->sync_cookie = cookie;
124121 event->name_len = len;
125122 if (len)
126
- strcpy(event->name, file_name);
123
+ strcpy(event->name, name->name);
127124
128125 ret = fsnotify_add_event(group, fsn_event, inotify_merge);
129126 if (ret) {
....@@ -202,7 +199,7 @@
202199 }
203200
204201 const struct fsnotify_ops inotify_fsnotify_ops = {
205
- .handle_event = inotify_handle_event,
202
+ .handle_inode_event = inotify_handle_inode_event,
206203 .free_group_priv = inotify_free_group_priv,
207204 .free_event = inotify_free_event,
208205 .freeing_mark = inotify_freeing_mark,