13e0a4e85SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
263c882a0SEric Paris /*
363c882a0SEric Paris * fs/inotify_user.c - inotify support for userspace
463c882a0SEric Paris *
563c882a0SEric Paris * Authors:
663c882a0SEric Paris * John McCutchan <ttb@tentacle.dhs.org>
763c882a0SEric Paris * Robert Love <rml@novell.com>
863c882a0SEric Paris *
963c882a0SEric Paris * Copyright (C) 2005 John McCutchan
1063c882a0SEric Paris * Copyright 2006 Hewlett-Packard Development Company, L.P.
1163c882a0SEric Paris *
1263c882a0SEric Paris * Copyright (C) 2009 Eric Paris <Red Hat Inc>
1363c882a0SEric Paris * inotify was largely rewriten to make use of the fsnotify infrastructure
1463c882a0SEric Paris */
1563c882a0SEric Paris
168c1934c8SEric Paris #include <linux/dcache.h> /* d_unlinked */
1763c882a0SEric Paris #include <linux/fs.h> /* struct inode */
1863c882a0SEric Paris #include <linux/fsnotify_backend.h>
1963c882a0SEric Paris #include <linux/inotify.h>
2063c882a0SEric Paris #include <linux/path.h> /* struct path */
2163c882a0SEric Paris #include <linux/slab.h> /* kmem_* */
2263c882a0SEric Paris #include <linux/types.h>
23b3b38d84SPavel Emelyanov #include <linux/sched.h>
245b825c3aSIngo Molnar #include <linux/sched/user.h>
25d46eb14bSShakeel Butt #include <linux/sched/mm.h>
2663c882a0SEric Paris
2763c882a0SEric Paris #include "inotify.h"
2863c882a0SEric Paris
2974766bbfSEric Paris /*
307053aee2SJan Kara * Check if 2 events contain the same information.
3174766bbfSEric Paris */
event_compare(struct fsnotify_event * old_fsn,struct fsnotify_event * new_fsn)327053aee2SJan Kara static bool event_compare(struct fsnotify_event *old_fsn,
337053aee2SJan Kara struct fsnotify_event *new_fsn)
3474766bbfSEric Paris {
357053aee2SJan Kara struct inotify_event_info *old, *new;
367053aee2SJan Kara
377053aee2SJan Kara old = INOTIFY_E(old_fsn);
387053aee2SJan Kara new = INOTIFY_E(new_fsn);
39a0a92d26SAmir Goldstein if (old->mask & FS_IN_IGNORED)
40a0a92d26SAmir Goldstein return false;
41a0a92d26SAmir Goldstein if ((old->mask == new->mask) &&
42956235afSAmir Goldstein (old->wd == new->wd) &&
437053aee2SJan Kara (old->name_len == new->name_len) &&
447053aee2SJan Kara (!old->name_len || !strcmp(old->name, new->name)))
4574766bbfSEric Paris return true;
4674766bbfSEric Paris return false;
4774766bbfSEric Paris }
4874766bbfSEric Paris
inotify_merge(struct fsnotify_group * group,struct fsnotify_event * event)4994e00d28SAmir Goldstein static int inotify_merge(struct fsnotify_group *group,
50f70ab54cSEric Paris struct fsnotify_event *event)
5174766bbfSEric Paris {
5294e00d28SAmir Goldstein struct list_head *list = &group->notification_list;
5374766bbfSEric Paris struct fsnotify_event *last_event;
5474766bbfSEric Paris
557053aee2SJan Kara last_event = list_entry(list->prev, struct fsnotify_event, list);
5683c0e1b4SJan Kara return event_compare(last_event, event);
5774766bbfSEric Paris }
5874766bbfSEric Paris
inotify_handle_inode_event(struct fsnotify_mark * inode_mark,u32 mask,struct inode * inode,struct inode * dir,const struct qstr * name,u32 cookie)591a2620a9SAmir Goldstein int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
601a2620a9SAmir Goldstein struct inode *inode, struct inode *dir,
611a2620a9SAmir Goldstein const struct qstr *name, u32 cookie)
6263c882a0SEric Paris {
63000285deSEric Paris struct inotify_inode_mark *i_mark;
647053aee2SJan Kara struct inotify_event_info *event;
657053aee2SJan Kara struct fsnotify_event *fsn_event;
661a2620a9SAmir Goldstein struct fsnotify_group *group = inode_mark->group;
6783c0e1b4SJan Kara int ret;
68*c915d8f5SJan Kara int len = 0, wd;
697053aee2SJan Kara int alloc_len = sizeof(struct inotify_event_info);
70b87d8cefSRoman Gushchin struct mem_cgroup *old_memcg;
7163c882a0SEric Paris
721a2620a9SAmir Goldstein if (name) {
731a2620a9SAmir Goldstein len = name->len;
747053aee2SJan Kara alloc_len += len + 1;
757053aee2SJan Kara }
765ba08e2eSEric Paris
77b54cecf5SAmir Goldstein pr_debug("%s: group=%p mark=%p mask=%x\n", __func__, group, inode_mark,
787053aee2SJan Kara mask);
7963c882a0SEric Paris
80ce8f76fbSEric Paris i_mark = container_of(inode_mark, struct inotify_inode_mark,
81000285deSEric Paris fsn_mark);
8263c882a0SEric Paris
83ec165450SShakeel Butt /*
84*c915d8f5SJan Kara * We can be racing with mark being detached. Don't report event with
85*c915d8f5SJan Kara * invalid wd.
86*c915d8f5SJan Kara */
87*c915d8f5SJan Kara wd = READ_ONCE(i_mark->wd);
88*c915d8f5SJan Kara if (wd == -1)
89*c915d8f5SJan Kara return 0;
90*c915d8f5SJan Kara /*
91ec165450SShakeel Butt * Whoever is interested in the event, pays for the allocation. Do not
92ec165450SShakeel Butt * trigger OOM killer in the target monitoring memcg as it may have
93ec165450SShakeel Butt * security repercussion.
94ec165450SShakeel Butt */
95b87d8cefSRoman Gushchin old_memcg = set_active_memcg(group->memcg);
96ec165450SShakeel Butt event = kmalloc(alloc_len, GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
97b87d8cefSRoman Gushchin set_active_memcg(old_memcg);
98d46eb14bSShakeel Butt
997b1f6417SJan Kara if (unlikely(!event)) {
1007b1f6417SJan Kara /*
1017b1f6417SJan Kara * Treat lost event due to ENOMEM the same way as queue
1027b1f6417SJan Kara * overflow to let userspace know event was lost.
1037b1f6417SJan Kara */
1047b1f6417SJan Kara fsnotify_queue_overflow(group);
10563c882a0SEric Paris return -ENOMEM;
1067b1f6417SJan Kara }
10763c882a0SEric Paris
1080a20df7eSAmir Goldstein /*
1090a20df7eSAmir Goldstein * We now report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
1100a20df7eSAmir Goldstein * for fanotify. inotify never reported IN_ISDIR with those events.
1110a20df7eSAmir Goldstein * It looks like an oversight, but to avoid the risk of breaking
1120a20df7eSAmir Goldstein * existing inotify programs, mask the flag out from those events.
1130a20df7eSAmir Goldstein */
1140a20df7eSAmir Goldstein if (mask & (IN_MOVE_SELF | IN_DELETE_SELF))
1150a20df7eSAmir Goldstein mask &= ~IN_ISDIR;
1160a20df7eSAmir Goldstein
1177053aee2SJan Kara fsn_event = &event->fse;
1188988f11aSAmir Goldstein fsnotify_init_event(fsn_event);
119a0a92d26SAmir Goldstein event->mask = mask;
120*c915d8f5SJan Kara event->wd = wd;
12145a22f4cSJan Kara event->sync_cookie = cookie;
1227053aee2SJan Kara event->name_len = len;
1237053aee2SJan Kara if (len)
1241a2620a9SAmir Goldstein strcpy(event->name, name->name);
12563c882a0SEric Paris
1261ad03c3aSGabriel Krisman Bertazi ret = fsnotify_add_event(group, fsn_event, inotify_merge);
12783c0e1b4SJan Kara if (ret) {
1287053aee2SJan Kara /* Our event wasn't used in the end. Free it. */
1297053aee2SJan Kara fsnotify_destroy_event(group, fsn_event);
130eef3a116SEric Paris }
13163c882a0SEric Paris
13238035c04SAmir Goldstein if (inode_mark->flags & FSNOTIFY_MARK_FLAG_IN_ONESHOT)
133e2a29943SLino Sanfilippo fsnotify_destroy_mark(inode_mark, group);
13463c882a0SEric Paris
13583c0e1b4SJan Kara return 0;
13663c882a0SEric Paris }
13763c882a0SEric Paris
inotify_freeing_mark(struct fsnotify_mark * fsn_mark,struct fsnotify_group * group)138000285deSEric Paris static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group)
13963c882a0SEric Paris {
140000285deSEric Paris inotify_ignored_and_remove_idr(fsn_mark, group);
14163c882a0SEric Paris }
14263c882a0SEric Paris
143cf437426SEric Paris /*
144cf437426SEric Paris * This is NEVER supposed to be called. Inotify marks should either have been
145cf437426SEric Paris * removed from the idr when the watch was removed or in the
146cf437426SEric Paris * fsnotify_destroy_mark_by_group() call when the inotify instance was being
147cf437426SEric Paris * torn down. This is only called if the idr is about to be freed but there
148cf437426SEric Paris * are still marks in it.
149cf437426SEric Paris */
idr_callback(int id,void * p,void * data)15063c882a0SEric Paris static int idr_callback(int id, void *p, void *data)
15163c882a0SEric Paris {
152000285deSEric Paris struct fsnotify_mark *fsn_mark;
153000285deSEric Paris struct inotify_inode_mark *i_mark;
154cf437426SEric Paris static bool warned = false;
155cf437426SEric Paris
156cf437426SEric Paris if (warned)
157cf437426SEric Paris return 0;
158cf437426SEric Paris
159976ae32bSEric Paris warned = true;
160000285deSEric Paris fsn_mark = p;
161000285deSEric Paris i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
162cf437426SEric Paris
163000285deSEric Paris WARN(1, "inotify closing but id=%d for fsn_mark=%p in group=%p still in "
164cf437426SEric Paris "idr. Probably leaking memory\n", id, p, data);
165cf437426SEric Paris
166cf437426SEric Paris /*
167cf437426SEric Paris * I'm taking the liberty of assuming that the mark in question is a
168cf437426SEric Paris * valid address and I'm dereferencing it. This might help to figure
169cf437426SEric Paris * out why we got here and the panic is no worse than the original
170cf437426SEric Paris * BUG() that was here.
171cf437426SEric Paris */
172000285deSEric Paris if (fsn_mark)
17325c829afSJan Kara printk(KERN_WARNING "fsn_mark->group=%p wd=%d\n",
17425c829afSJan Kara fsn_mark->group, i_mark->wd);
17563c882a0SEric Paris return 0;
17663c882a0SEric Paris }
17763c882a0SEric Paris
inotify_free_group_priv(struct fsnotify_group * group)17863c882a0SEric Paris static void inotify_free_group_priv(struct fsnotify_group *group)
17963c882a0SEric Paris {
18025985edcSLucas De Marchi /* ideally the idr is empty and we won't hit the BUG in the callback */
181cf437426SEric Paris idr_for_each(&group->inotify_data.idr, idr_callback, group);
18263c882a0SEric Paris idr_destroy(&group->inotify_data.idr);
1831cce1eeaSNikolay Borisov if (group->inotify_data.ucounts)
1841cce1eeaSNikolay Borisov dec_inotify_instances(group->inotify_data.ucounts);
185105d1b42SSasha Levin }
18663c882a0SEric Paris
inotify_free_event(struct fsnotify_group * group,struct fsnotify_event * fsn_event)187330ae77dSGabriel Krisman Bertazi static void inotify_free_event(struct fsnotify_group *group,
188330ae77dSGabriel Krisman Bertazi struct fsnotify_event *fsn_event)
18963c882a0SEric Paris {
1907053aee2SJan Kara kfree(INOTIFY_E(fsn_event));
19163c882a0SEric Paris }
19263c882a0SEric Paris
193054c636eSJan Kara /* ding dong the mark is dead */
inotify_free_mark(struct fsnotify_mark * fsn_mark)194054c636eSJan Kara static void inotify_free_mark(struct fsnotify_mark *fsn_mark)
195054c636eSJan Kara {
196054c636eSJan Kara struct inotify_inode_mark *i_mark;
197054c636eSJan Kara
198054c636eSJan Kara i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
199054c636eSJan Kara
200054c636eSJan Kara kmem_cache_free(inotify_inode_mark_cachep, i_mark);
201054c636eSJan Kara }
202054c636eSJan Kara
20363c882a0SEric Paris const struct fsnotify_ops inotify_fsnotify_ops = {
2041a2620a9SAmir Goldstein .handle_inode_event = inotify_handle_inode_event,
20563c882a0SEric Paris .free_group_priv = inotify_free_group_priv,
2067053aee2SJan Kara .free_event = inotify_free_event,
20763c882a0SEric Paris .freeing_mark = inotify_freeing_mark,
208054c636eSJan Kara .free_mark = inotify_free_mark,
20963c882a0SEric Paris };
210