1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * fs/inotify_user.c - inotify support for userspace
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Authors:
6*4882a593Smuzhiyun * John McCutchan <ttb@tentacle.dhs.org>
7*4882a593Smuzhiyun * Robert Love <rml@novell.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Copyright (C) 2005 John McCutchan
10*4882a593Smuzhiyun * Copyright 2006 Hewlett-Packard Development Company, L.P.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Copyright (C) 2009 Eric Paris <Red Hat Inc>
13*4882a593Smuzhiyun * inotify was largely rewriten to make use of the fsnotify infrastructure
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <linux/file.h>
17*4882a593Smuzhiyun #include <linux/fs.h> /* struct inode */
18*4882a593Smuzhiyun #include <linux/fsnotify_backend.h>
19*4882a593Smuzhiyun #include <linux/idr.h>
20*4882a593Smuzhiyun #include <linux/init.h> /* fs_initcall */
21*4882a593Smuzhiyun #include <linux/inotify.h>
22*4882a593Smuzhiyun #include <linux/kernel.h> /* roundup() */
23*4882a593Smuzhiyun #include <linux/namei.h> /* LOOKUP_FOLLOW */
24*4882a593Smuzhiyun #include <linux/sched/signal.h>
25*4882a593Smuzhiyun #include <linux/slab.h> /* struct kmem_cache */
26*4882a593Smuzhiyun #include <linux/syscalls.h>
27*4882a593Smuzhiyun #include <linux/types.h>
28*4882a593Smuzhiyun #include <linux/anon_inodes.h>
29*4882a593Smuzhiyun #include <linux/uaccess.h>
30*4882a593Smuzhiyun #include <linux/poll.h>
31*4882a593Smuzhiyun #include <linux/wait.h>
32*4882a593Smuzhiyun #include <linux/memcontrol.h>
33*4882a593Smuzhiyun #include <linux/security.h>
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include "inotify.h"
36*4882a593Smuzhiyun #include "../fdinfo.h"
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include <asm/ioctls.h>
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /* configurable via /proc/sys/fs/inotify/ */
41*4882a593Smuzhiyun static int inotify_max_queued_events __read_mostly;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun struct kmem_cache *inotify_inode_mark_cachep __read_mostly;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #ifdef CONFIG_SYSCTL
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #include <linux/sysctl.h>
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun struct ctl_table inotify_table[] = {
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun .procname = "max_user_instances",
52*4882a593Smuzhiyun .data = &init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES],
53*4882a593Smuzhiyun .maxlen = sizeof(int),
54*4882a593Smuzhiyun .mode = 0644,
55*4882a593Smuzhiyun .proc_handler = proc_dointvec_minmax,
56*4882a593Smuzhiyun .extra1 = SYSCTL_ZERO,
57*4882a593Smuzhiyun },
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun .procname = "max_user_watches",
60*4882a593Smuzhiyun .data = &init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES],
61*4882a593Smuzhiyun .maxlen = sizeof(int),
62*4882a593Smuzhiyun .mode = 0644,
63*4882a593Smuzhiyun .proc_handler = proc_dointvec_minmax,
64*4882a593Smuzhiyun .extra1 = SYSCTL_ZERO,
65*4882a593Smuzhiyun },
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun .procname = "max_queued_events",
68*4882a593Smuzhiyun .data = &inotify_max_queued_events,
69*4882a593Smuzhiyun .maxlen = sizeof(int),
70*4882a593Smuzhiyun .mode = 0644,
71*4882a593Smuzhiyun .proc_handler = proc_dointvec_minmax,
72*4882a593Smuzhiyun .extra1 = SYSCTL_ZERO
73*4882a593Smuzhiyun },
74*4882a593Smuzhiyun { }
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun #endif /* CONFIG_SYSCTL */
77*4882a593Smuzhiyun
inotify_arg_to_mask(struct inode * inode,u32 arg)78*4882a593Smuzhiyun static inline __u32 inotify_arg_to_mask(struct inode *inode, u32 arg)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun __u32 mask;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /*
83*4882a593Smuzhiyun * Everything should accept their own ignored and should receive events
84*4882a593Smuzhiyun * when the inode is unmounted. All directories care about children.
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun mask = (FS_IN_IGNORED | FS_UNMOUNT);
87*4882a593Smuzhiyun if (S_ISDIR(inode->i_mode))
88*4882a593Smuzhiyun mask |= FS_EVENT_ON_CHILD;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* mask off the flags used to open the fd */
91*4882a593Smuzhiyun mask |= (arg & INOTIFY_USER_MASK);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun return mask;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
inotify_mask_to_arg(__u32 mask)96*4882a593Smuzhiyun static inline u32 inotify_mask_to_arg(__u32 mask)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun return mask & (IN_ALL_EVENTS | IN_ISDIR | IN_UNMOUNT | IN_IGNORED |
99*4882a593Smuzhiyun IN_Q_OVERFLOW);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* intofiy userspace file descriptor functions */
inotify_poll(struct file * file,poll_table * wait)103*4882a593Smuzhiyun static __poll_t inotify_poll(struct file *file, poll_table *wait)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct fsnotify_group *group = file->private_data;
106*4882a593Smuzhiyun __poll_t ret = 0;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun poll_wait(file, &group->notification_waitq, wait);
109*4882a593Smuzhiyun spin_lock(&group->notification_lock);
110*4882a593Smuzhiyun if (!fsnotify_notify_queue_is_empty(group))
111*4882a593Smuzhiyun ret = EPOLLIN | EPOLLRDNORM;
112*4882a593Smuzhiyun spin_unlock(&group->notification_lock);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun return ret;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
round_event_name_len(struct fsnotify_event * fsn_event)117*4882a593Smuzhiyun static int round_event_name_len(struct fsnotify_event *fsn_event)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun struct inotify_event_info *event;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun event = INOTIFY_E(fsn_event);
122*4882a593Smuzhiyun if (!event->name_len)
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun return roundup(event->name_len + 1, sizeof(struct inotify_event));
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun * Get an inotify_kernel_event if one exists and is small
129*4882a593Smuzhiyun * enough to fit in "count". Return an error pointer if
130*4882a593Smuzhiyun * not large enough.
131*4882a593Smuzhiyun *
132*4882a593Smuzhiyun * Called with the group->notification_lock held.
133*4882a593Smuzhiyun */
get_one_event(struct fsnotify_group * group,size_t count)134*4882a593Smuzhiyun static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
135*4882a593Smuzhiyun size_t count)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun size_t event_size = sizeof(struct inotify_event);
138*4882a593Smuzhiyun struct fsnotify_event *event;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (fsnotify_notify_queue_is_empty(group))
141*4882a593Smuzhiyun return NULL;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun event = fsnotify_peek_first_event(group);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun pr_debug("%s: group=%p event=%p\n", __func__, group, event);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun event_size += round_event_name_len(event);
148*4882a593Smuzhiyun if (event_size > count)
149*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* held the notification_lock the whole time, so this is the
152*4882a593Smuzhiyun * same event we peeked above */
153*4882a593Smuzhiyun fsnotify_remove_first_event(group);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return event;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /*
159*4882a593Smuzhiyun * Copy an event to user space, returning how much we copied.
160*4882a593Smuzhiyun *
161*4882a593Smuzhiyun * We already checked that the event size is smaller than the
162*4882a593Smuzhiyun * buffer we had in "get_one_event()" above.
163*4882a593Smuzhiyun */
copy_event_to_user(struct fsnotify_group * group,struct fsnotify_event * fsn_event,char __user * buf)164*4882a593Smuzhiyun static ssize_t copy_event_to_user(struct fsnotify_group *group,
165*4882a593Smuzhiyun struct fsnotify_event *fsn_event,
166*4882a593Smuzhiyun char __user *buf)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun struct inotify_event inotify_event;
169*4882a593Smuzhiyun struct inotify_event_info *event;
170*4882a593Smuzhiyun size_t event_size = sizeof(struct inotify_event);
171*4882a593Smuzhiyun size_t name_len;
172*4882a593Smuzhiyun size_t pad_name_len;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun event = INOTIFY_E(fsn_event);
177*4882a593Smuzhiyun name_len = event->name_len;
178*4882a593Smuzhiyun /*
179*4882a593Smuzhiyun * round up name length so it is a multiple of event_size
180*4882a593Smuzhiyun * plus an extra byte for the terminating '\0'.
181*4882a593Smuzhiyun */
182*4882a593Smuzhiyun pad_name_len = round_event_name_len(fsn_event);
183*4882a593Smuzhiyun inotify_event.len = pad_name_len;
184*4882a593Smuzhiyun inotify_event.mask = inotify_mask_to_arg(event->mask);
185*4882a593Smuzhiyun inotify_event.wd = event->wd;
186*4882a593Smuzhiyun inotify_event.cookie = event->sync_cookie;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* send the main event */
189*4882a593Smuzhiyun if (copy_to_user(buf, &inotify_event, event_size))
190*4882a593Smuzhiyun return -EFAULT;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun buf += event_size;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /*
195*4882a593Smuzhiyun * fsnotify only stores the pathname, so here we have to send the pathname
196*4882a593Smuzhiyun * and then pad that pathname out to a multiple of sizeof(inotify_event)
197*4882a593Smuzhiyun * with zeros.
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun if (pad_name_len) {
200*4882a593Smuzhiyun /* copy the path name */
201*4882a593Smuzhiyun if (copy_to_user(buf, event->name, name_len))
202*4882a593Smuzhiyun return -EFAULT;
203*4882a593Smuzhiyun buf += name_len;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /* fill userspace with 0's */
206*4882a593Smuzhiyun if (clear_user(buf, pad_name_len - name_len))
207*4882a593Smuzhiyun return -EFAULT;
208*4882a593Smuzhiyun event_size += pad_name_len;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun return event_size;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
inotify_read(struct file * file,char __user * buf,size_t count,loff_t * pos)214*4882a593Smuzhiyun static ssize_t inotify_read(struct file *file, char __user *buf,
215*4882a593Smuzhiyun size_t count, loff_t *pos)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct fsnotify_group *group;
218*4882a593Smuzhiyun struct fsnotify_event *kevent;
219*4882a593Smuzhiyun char __user *start;
220*4882a593Smuzhiyun int ret;
221*4882a593Smuzhiyun DEFINE_WAIT_FUNC(wait, woken_wake_function);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun start = buf;
224*4882a593Smuzhiyun group = file->private_data;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun add_wait_queue(&group->notification_waitq, &wait);
227*4882a593Smuzhiyun while (1) {
228*4882a593Smuzhiyun spin_lock(&group->notification_lock);
229*4882a593Smuzhiyun kevent = get_one_event(group, count);
230*4882a593Smuzhiyun spin_unlock(&group->notification_lock);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun pr_debug("%s: group=%p kevent=%p\n", __func__, group, kevent);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (kevent) {
235*4882a593Smuzhiyun ret = PTR_ERR(kevent);
236*4882a593Smuzhiyun if (IS_ERR(kevent))
237*4882a593Smuzhiyun break;
238*4882a593Smuzhiyun ret = copy_event_to_user(group, kevent, buf);
239*4882a593Smuzhiyun fsnotify_destroy_event(group, kevent);
240*4882a593Smuzhiyun if (ret < 0)
241*4882a593Smuzhiyun break;
242*4882a593Smuzhiyun buf += ret;
243*4882a593Smuzhiyun count -= ret;
244*4882a593Smuzhiyun continue;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun ret = -EAGAIN;
248*4882a593Smuzhiyun if (file->f_flags & O_NONBLOCK)
249*4882a593Smuzhiyun break;
250*4882a593Smuzhiyun ret = -ERESTARTSYS;
251*4882a593Smuzhiyun if (signal_pending(current))
252*4882a593Smuzhiyun break;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (start != buf)
255*4882a593Smuzhiyun break;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun remove_wait_queue(&group->notification_waitq, &wait);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (start != buf && ret != -EFAULT)
262*4882a593Smuzhiyun ret = buf - start;
263*4882a593Smuzhiyun return ret;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
inotify_release(struct inode * ignored,struct file * file)266*4882a593Smuzhiyun static int inotify_release(struct inode *ignored, struct file *file)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun struct fsnotify_group *group = file->private_data;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun pr_debug("%s: group=%p\n", __func__, group);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* free this group, matching get was inotify_init->fsnotify_obtain_group */
273*4882a593Smuzhiyun fsnotify_destroy_group(group);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
inotify_ioctl(struct file * file,unsigned int cmd,unsigned long arg)278*4882a593Smuzhiyun static long inotify_ioctl(struct file *file, unsigned int cmd,
279*4882a593Smuzhiyun unsigned long arg)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun struct fsnotify_group *group;
282*4882a593Smuzhiyun struct fsnotify_event *fsn_event;
283*4882a593Smuzhiyun void __user *p;
284*4882a593Smuzhiyun int ret = -ENOTTY;
285*4882a593Smuzhiyun size_t send_len = 0;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun group = file->private_data;
288*4882a593Smuzhiyun p = (void __user *) arg;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun pr_debug("%s: group=%p cmd=%u\n", __func__, group, cmd);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun switch (cmd) {
293*4882a593Smuzhiyun case FIONREAD:
294*4882a593Smuzhiyun spin_lock(&group->notification_lock);
295*4882a593Smuzhiyun list_for_each_entry(fsn_event, &group->notification_list,
296*4882a593Smuzhiyun list) {
297*4882a593Smuzhiyun send_len += sizeof(struct inotify_event);
298*4882a593Smuzhiyun send_len += round_event_name_len(fsn_event);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun spin_unlock(&group->notification_lock);
301*4882a593Smuzhiyun ret = put_user(send_len, (int __user *) p);
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun #ifdef CONFIG_CHECKPOINT_RESTORE
304*4882a593Smuzhiyun case INOTIFY_IOC_SETNEXTWD:
305*4882a593Smuzhiyun ret = -EINVAL;
306*4882a593Smuzhiyun if (arg >= 1 && arg <= INT_MAX) {
307*4882a593Smuzhiyun struct inotify_group_private_data *data;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun data = &group->inotify_data;
310*4882a593Smuzhiyun spin_lock(&data->idr_lock);
311*4882a593Smuzhiyun idr_set_cursor(&data->idr, (unsigned int)arg);
312*4882a593Smuzhiyun spin_unlock(&data->idr_lock);
313*4882a593Smuzhiyun ret = 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun #endif /* CONFIG_CHECKPOINT_RESTORE */
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun return ret;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static const struct file_operations inotify_fops = {
323*4882a593Smuzhiyun .show_fdinfo = inotify_show_fdinfo,
324*4882a593Smuzhiyun .poll = inotify_poll,
325*4882a593Smuzhiyun .read = inotify_read,
326*4882a593Smuzhiyun .fasync = fsnotify_fasync,
327*4882a593Smuzhiyun .release = inotify_release,
328*4882a593Smuzhiyun .unlocked_ioctl = inotify_ioctl,
329*4882a593Smuzhiyun .compat_ioctl = inotify_ioctl,
330*4882a593Smuzhiyun .llseek = noop_llseek,
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /*
335*4882a593Smuzhiyun * find_inode - resolve a user-given path to a specific inode
336*4882a593Smuzhiyun */
inotify_find_inode(const char __user * dirname,struct path * path,unsigned int flags,__u64 mask)337*4882a593Smuzhiyun static int inotify_find_inode(const char __user *dirname, struct path *path,
338*4882a593Smuzhiyun unsigned int flags, __u64 mask)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun int error;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun error = user_path_at(AT_FDCWD, dirname, flags, path);
343*4882a593Smuzhiyun if (error)
344*4882a593Smuzhiyun return error;
345*4882a593Smuzhiyun /* you can only watch an inode if you have read permissions on it */
346*4882a593Smuzhiyun error = inode_permission(path->dentry->d_inode, MAY_READ);
347*4882a593Smuzhiyun if (error) {
348*4882a593Smuzhiyun path_put(path);
349*4882a593Smuzhiyun return error;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun error = security_path_notify(path, mask,
352*4882a593Smuzhiyun FSNOTIFY_OBJ_TYPE_INODE);
353*4882a593Smuzhiyun if (error)
354*4882a593Smuzhiyun path_put(path);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return error;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
inotify_add_to_idr(struct idr * idr,spinlock_t * idr_lock,struct inotify_inode_mark * i_mark)359*4882a593Smuzhiyun static int inotify_add_to_idr(struct idr *idr, spinlock_t *idr_lock,
360*4882a593Smuzhiyun struct inotify_inode_mark *i_mark)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun int ret;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun idr_preload(GFP_KERNEL);
365*4882a593Smuzhiyun spin_lock(idr_lock);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun ret = idr_alloc_cyclic(idr, i_mark, 1, 0, GFP_NOWAIT);
368*4882a593Smuzhiyun if (ret >= 0) {
369*4882a593Smuzhiyun /* we added the mark to the idr, take a reference */
370*4882a593Smuzhiyun i_mark->wd = ret;
371*4882a593Smuzhiyun fsnotify_get_mark(&i_mark->fsn_mark);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun spin_unlock(idr_lock);
375*4882a593Smuzhiyun idr_preload_end();
376*4882a593Smuzhiyun return ret < 0 ? ret : 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
inotify_idr_find_locked(struct fsnotify_group * group,int wd)379*4882a593Smuzhiyun static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group *group,
380*4882a593Smuzhiyun int wd)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun struct idr *idr = &group->inotify_data.idr;
383*4882a593Smuzhiyun spinlock_t *idr_lock = &group->inotify_data.idr_lock;
384*4882a593Smuzhiyun struct inotify_inode_mark *i_mark;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun assert_spin_locked(idr_lock);
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun i_mark = idr_find(idr, wd);
389*4882a593Smuzhiyun if (i_mark) {
390*4882a593Smuzhiyun struct fsnotify_mark *fsn_mark = &i_mark->fsn_mark;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun fsnotify_get_mark(fsn_mark);
393*4882a593Smuzhiyun /* One ref for being in the idr, one ref we just took */
394*4882a593Smuzhiyun BUG_ON(refcount_read(&fsn_mark->refcnt) < 2);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun return i_mark;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
inotify_idr_find(struct fsnotify_group * group,int wd)400*4882a593Smuzhiyun static struct inotify_inode_mark *inotify_idr_find(struct fsnotify_group *group,
401*4882a593Smuzhiyun int wd)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun struct inotify_inode_mark *i_mark;
404*4882a593Smuzhiyun spinlock_t *idr_lock = &group->inotify_data.idr_lock;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun spin_lock(idr_lock);
407*4882a593Smuzhiyun i_mark = inotify_idr_find_locked(group, wd);
408*4882a593Smuzhiyun spin_unlock(idr_lock);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun return i_mark;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /*
414*4882a593Smuzhiyun * Remove the mark from the idr (if present) and drop the reference
415*4882a593Smuzhiyun * on the mark because it was in the idr.
416*4882a593Smuzhiyun */
inotify_remove_from_idr(struct fsnotify_group * group,struct inotify_inode_mark * i_mark)417*4882a593Smuzhiyun static void inotify_remove_from_idr(struct fsnotify_group *group,
418*4882a593Smuzhiyun struct inotify_inode_mark *i_mark)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun struct idr *idr = &group->inotify_data.idr;
421*4882a593Smuzhiyun spinlock_t *idr_lock = &group->inotify_data.idr_lock;
422*4882a593Smuzhiyun struct inotify_inode_mark *found_i_mark = NULL;
423*4882a593Smuzhiyun int wd;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun spin_lock(idr_lock);
426*4882a593Smuzhiyun wd = i_mark->wd;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /*
429*4882a593Smuzhiyun * does this i_mark think it is in the idr? we shouldn't get called
430*4882a593Smuzhiyun * if it wasn't....
431*4882a593Smuzhiyun */
432*4882a593Smuzhiyun if (wd == -1) {
433*4882a593Smuzhiyun WARN_ONCE(1, "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p\n",
434*4882a593Smuzhiyun __func__, i_mark, i_mark->wd, i_mark->fsn_mark.group);
435*4882a593Smuzhiyun goto out;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* Lets look in the idr to see if we find it */
439*4882a593Smuzhiyun found_i_mark = inotify_idr_find_locked(group, wd);
440*4882a593Smuzhiyun if (unlikely(!found_i_mark)) {
441*4882a593Smuzhiyun WARN_ONCE(1, "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p\n",
442*4882a593Smuzhiyun __func__, i_mark, i_mark->wd, i_mark->fsn_mark.group);
443*4882a593Smuzhiyun goto out;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /*
447*4882a593Smuzhiyun * We found an mark in the idr at the right wd, but it's
448*4882a593Smuzhiyun * not the mark we were told to remove. eparis seriously
449*4882a593Smuzhiyun * fucked up somewhere.
450*4882a593Smuzhiyun */
451*4882a593Smuzhiyun if (unlikely(found_i_mark != i_mark)) {
452*4882a593Smuzhiyun WARN_ONCE(1, "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p "
453*4882a593Smuzhiyun "found_i_mark=%p found_i_mark->wd=%d "
454*4882a593Smuzhiyun "found_i_mark->group=%p\n", __func__, i_mark,
455*4882a593Smuzhiyun i_mark->wd, i_mark->fsn_mark.group, found_i_mark,
456*4882a593Smuzhiyun found_i_mark->wd, found_i_mark->fsn_mark.group);
457*4882a593Smuzhiyun goto out;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /*
461*4882a593Smuzhiyun * One ref for being in the idr
462*4882a593Smuzhiyun * one ref grabbed by inotify_idr_find
463*4882a593Smuzhiyun */
464*4882a593Smuzhiyun if (unlikely(refcount_read(&i_mark->fsn_mark.refcnt) < 2)) {
465*4882a593Smuzhiyun printk(KERN_ERR "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p\n",
466*4882a593Smuzhiyun __func__, i_mark, i_mark->wd, i_mark->fsn_mark.group);
467*4882a593Smuzhiyun /* we can't really recover with bad ref cnting.. */
468*4882a593Smuzhiyun BUG();
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun idr_remove(idr, wd);
472*4882a593Smuzhiyun /* Removed from the idr, drop that ref. */
473*4882a593Smuzhiyun fsnotify_put_mark(&i_mark->fsn_mark);
474*4882a593Smuzhiyun out:
475*4882a593Smuzhiyun i_mark->wd = -1;
476*4882a593Smuzhiyun spin_unlock(idr_lock);
477*4882a593Smuzhiyun /* match the ref taken by inotify_idr_find_locked() */
478*4882a593Smuzhiyun if (found_i_mark)
479*4882a593Smuzhiyun fsnotify_put_mark(&found_i_mark->fsn_mark);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun * Send IN_IGNORED for this wd, remove this wd from the idr.
484*4882a593Smuzhiyun */
inotify_ignored_and_remove_idr(struct fsnotify_mark * fsn_mark,struct fsnotify_group * group)485*4882a593Smuzhiyun void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
486*4882a593Smuzhiyun struct fsnotify_group *group)
487*4882a593Smuzhiyun {
488*4882a593Smuzhiyun struct inotify_inode_mark *i_mark;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /* Queue ignore event for the watch */
491*4882a593Smuzhiyun inotify_handle_inode_event(fsn_mark, FS_IN_IGNORED, NULL, NULL, NULL,
492*4882a593Smuzhiyun 0);
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
495*4882a593Smuzhiyun /* remove this mark from the idr */
496*4882a593Smuzhiyun inotify_remove_from_idr(group, i_mark);
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun dec_inotify_watches(group->inotify_data.ucounts);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
inotify_update_existing_watch(struct fsnotify_group * group,struct inode * inode,u32 arg)501*4882a593Smuzhiyun static int inotify_update_existing_watch(struct fsnotify_group *group,
502*4882a593Smuzhiyun struct inode *inode,
503*4882a593Smuzhiyun u32 arg)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun struct fsnotify_mark *fsn_mark;
506*4882a593Smuzhiyun struct inotify_inode_mark *i_mark;
507*4882a593Smuzhiyun __u32 old_mask, new_mask;
508*4882a593Smuzhiyun __u32 mask;
509*4882a593Smuzhiyun int add = (arg & IN_MASK_ADD);
510*4882a593Smuzhiyun int create = (arg & IN_MASK_CREATE);
511*4882a593Smuzhiyun int ret;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun mask = inotify_arg_to_mask(inode, arg);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
516*4882a593Smuzhiyun if (!fsn_mark)
517*4882a593Smuzhiyun return -ENOENT;
518*4882a593Smuzhiyun else if (create) {
519*4882a593Smuzhiyun ret = -EEXIST;
520*4882a593Smuzhiyun goto out;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun spin_lock(&fsn_mark->lock);
526*4882a593Smuzhiyun old_mask = fsn_mark->mask;
527*4882a593Smuzhiyun if (add)
528*4882a593Smuzhiyun fsn_mark->mask |= mask;
529*4882a593Smuzhiyun else
530*4882a593Smuzhiyun fsn_mark->mask = mask;
531*4882a593Smuzhiyun new_mask = fsn_mark->mask;
532*4882a593Smuzhiyun spin_unlock(&fsn_mark->lock);
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if (old_mask != new_mask) {
535*4882a593Smuzhiyun /* more bits in old than in new? */
536*4882a593Smuzhiyun int dropped = (old_mask & ~new_mask);
537*4882a593Smuzhiyun /* more bits in this fsn_mark than the inode's mask? */
538*4882a593Smuzhiyun int do_inode = (new_mask & ~inode->i_fsnotify_mask);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /* update the inode with this new fsn_mark */
541*4882a593Smuzhiyun if (dropped || do_inode)
542*4882a593Smuzhiyun fsnotify_recalc_mask(inode->i_fsnotify_marks);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun /* return the wd */
547*4882a593Smuzhiyun ret = i_mark->wd;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun out:
550*4882a593Smuzhiyun /* match the get from fsnotify_find_mark() */
551*4882a593Smuzhiyun fsnotify_put_mark(fsn_mark);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun return ret;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
inotify_new_watch(struct fsnotify_group * group,struct inode * inode,u32 arg)556*4882a593Smuzhiyun static int inotify_new_watch(struct fsnotify_group *group,
557*4882a593Smuzhiyun struct inode *inode,
558*4882a593Smuzhiyun u32 arg)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct inotify_inode_mark *tmp_i_mark;
561*4882a593Smuzhiyun __u32 mask;
562*4882a593Smuzhiyun int ret;
563*4882a593Smuzhiyun struct idr *idr = &group->inotify_data.idr;
564*4882a593Smuzhiyun spinlock_t *idr_lock = &group->inotify_data.idr_lock;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun mask = inotify_arg_to_mask(inode, arg);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
569*4882a593Smuzhiyun if (unlikely(!tmp_i_mark))
570*4882a593Smuzhiyun return -ENOMEM;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun fsnotify_init_mark(&tmp_i_mark->fsn_mark, group);
573*4882a593Smuzhiyun tmp_i_mark->fsn_mark.mask = mask;
574*4882a593Smuzhiyun tmp_i_mark->wd = -1;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun ret = inotify_add_to_idr(idr, idr_lock, tmp_i_mark);
577*4882a593Smuzhiyun if (ret)
578*4882a593Smuzhiyun goto out_err;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun /* increment the number of watches the user has */
581*4882a593Smuzhiyun if (!inc_inotify_watches(group->inotify_data.ucounts)) {
582*4882a593Smuzhiyun inotify_remove_from_idr(group, tmp_i_mark);
583*4882a593Smuzhiyun ret = -ENOSPC;
584*4882a593Smuzhiyun goto out_err;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun /* we are on the idr, now get on the inode */
588*4882a593Smuzhiyun ret = fsnotify_add_inode_mark_locked(&tmp_i_mark->fsn_mark, inode, 0);
589*4882a593Smuzhiyun if (ret) {
590*4882a593Smuzhiyun /* we failed to get on the inode, get off the idr */
591*4882a593Smuzhiyun inotify_remove_from_idr(group, tmp_i_mark);
592*4882a593Smuzhiyun goto out_err;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun /* return the watch descriptor for this new mark */
597*4882a593Smuzhiyun ret = tmp_i_mark->wd;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun out_err:
600*4882a593Smuzhiyun /* match the ref from fsnotify_init_mark() */
601*4882a593Smuzhiyun fsnotify_put_mark(&tmp_i_mark->fsn_mark);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun return ret;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun
inotify_update_watch(struct fsnotify_group * group,struct inode * inode,u32 arg)606*4882a593Smuzhiyun static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun int ret = 0;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun mutex_lock(&group->mark_mutex);
611*4882a593Smuzhiyun /* try to update and existing watch with the new arg */
612*4882a593Smuzhiyun ret = inotify_update_existing_watch(group, inode, arg);
613*4882a593Smuzhiyun /* no mark present, try to add a new one */
614*4882a593Smuzhiyun if (ret == -ENOENT)
615*4882a593Smuzhiyun ret = inotify_new_watch(group, inode, arg);
616*4882a593Smuzhiyun mutex_unlock(&group->mark_mutex);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun return ret;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
inotify_new_group(unsigned int max_events)621*4882a593Smuzhiyun static struct fsnotify_group *inotify_new_group(unsigned int max_events)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun struct fsnotify_group *group;
624*4882a593Smuzhiyun struct inotify_event_info *oevent;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun group = fsnotify_alloc_group(&inotify_fsnotify_ops);
627*4882a593Smuzhiyun if (IS_ERR(group))
628*4882a593Smuzhiyun return group;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL);
631*4882a593Smuzhiyun if (unlikely(!oevent)) {
632*4882a593Smuzhiyun fsnotify_destroy_group(group);
633*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun group->overflow_event = &oevent->fse;
636*4882a593Smuzhiyun fsnotify_init_event(group->overflow_event, 0);
637*4882a593Smuzhiyun oevent->mask = FS_Q_OVERFLOW;
638*4882a593Smuzhiyun oevent->wd = -1;
639*4882a593Smuzhiyun oevent->sync_cookie = 0;
640*4882a593Smuzhiyun oevent->name_len = 0;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun group->max_events = max_events;
643*4882a593Smuzhiyun group->memcg = get_mem_cgroup_from_mm(current->mm);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun spin_lock_init(&group->inotify_data.idr_lock);
646*4882a593Smuzhiyun idr_init(&group->inotify_data.idr);
647*4882a593Smuzhiyun group->inotify_data.ucounts = inc_ucount(current_user_ns(),
648*4882a593Smuzhiyun current_euid(),
649*4882a593Smuzhiyun UCOUNT_INOTIFY_INSTANCES);
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun if (!group->inotify_data.ucounts) {
652*4882a593Smuzhiyun fsnotify_destroy_group(group);
653*4882a593Smuzhiyun return ERR_PTR(-EMFILE);
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun return group;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun /* inotify syscalls */
do_inotify_init(int flags)661*4882a593Smuzhiyun static int do_inotify_init(int flags)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun struct fsnotify_group *group;
664*4882a593Smuzhiyun int ret;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun /* Check the IN_* constants for consistency. */
667*4882a593Smuzhiyun BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC);
668*4882a593Smuzhiyun BUILD_BUG_ON(IN_NONBLOCK != O_NONBLOCK);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
671*4882a593Smuzhiyun return -EINVAL;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun /* fsnotify_obtain_group took a reference to group, we put this when we kill the file in the end */
674*4882a593Smuzhiyun group = inotify_new_group(inotify_max_queued_events);
675*4882a593Smuzhiyun if (IS_ERR(group))
676*4882a593Smuzhiyun return PTR_ERR(group);
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun ret = anon_inode_getfd("inotify", &inotify_fops, group,
679*4882a593Smuzhiyun O_RDONLY | flags);
680*4882a593Smuzhiyun if (ret < 0)
681*4882a593Smuzhiyun fsnotify_destroy_group(group);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return ret;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
SYSCALL_DEFINE1(inotify_init1,int,flags)686*4882a593Smuzhiyun SYSCALL_DEFINE1(inotify_init1, int, flags)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun return do_inotify_init(flags);
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
SYSCALL_DEFINE0(inotify_init)691*4882a593Smuzhiyun SYSCALL_DEFINE0(inotify_init)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun return do_inotify_init(0);
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
SYSCALL_DEFINE3(inotify_add_watch,int,fd,const char __user *,pathname,u32,mask)696*4882a593Smuzhiyun SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
697*4882a593Smuzhiyun u32, mask)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun struct fsnotify_group *group;
700*4882a593Smuzhiyun struct inode *inode;
701*4882a593Smuzhiyun struct path path;
702*4882a593Smuzhiyun struct path alteredpath;
703*4882a593Smuzhiyun struct path *canonical_path = &path;
704*4882a593Smuzhiyun struct fd f;
705*4882a593Smuzhiyun int ret;
706*4882a593Smuzhiyun unsigned flags = 0;
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /*
709*4882a593Smuzhiyun * We share a lot of code with fs/dnotify. We also share
710*4882a593Smuzhiyun * the bit layout between inotify's IN_* and the fsnotify
711*4882a593Smuzhiyun * FS_*. This check ensures that only the inotify IN_*
712*4882a593Smuzhiyun * bits get passed in and set in watches/events.
713*4882a593Smuzhiyun */
714*4882a593Smuzhiyun if (unlikely(mask & ~ALL_INOTIFY_BITS))
715*4882a593Smuzhiyun return -EINVAL;
716*4882a593Smuzhiyun /*
717*4882a593Smuzhiyun * Require at least one valid bit set in the mask.
718*4882a593Smuzhiyun * Without _something_ set, we would have no events to
719*4882a593Smuzhiyun * watch for.
720*4882a593Smuzhiyun */
721*4882a593Smuzhiyun if (unlikely(!(mask & ALL_INOTIFY_BITS)))
722*4882a593Smuzhiyun return -EINVAL;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun f = fdget(fd);
725*4882a593Smuzhiyun if (unlikely(!f.file))
726*4882a593Smuzhiyun return -EBADF;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
729*4882a593Smuzhiyun if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE))) {
730*4882a593Smuzhiyun ret = -EINVAL;
731*4882a593Smuzhiyun goto fput_and_out;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun /* verify that this is indeed an inotify instance */
735*4882a593Smuzhiyun if (unlikely(f.file->f_op != &inotify_fops)) {
736*4882a593Smuzhiyun ret = -EINVAL;
737*4882a593Smuzhiyun goto fput_and_out;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun if (!(mask & IN_DONT_FOLLOW))
741*4882a593Smuzhiyun flags |= LOOKUP_FOLLOW;
742*4882a593Smuzhiyun if (mask & IN_ONLYDIR)
743*4882a593Smuzhiyun flags |= LOOKUP_DIRECTORY;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun ret = inotify_find_inode(pathname, &path, flags,
746*4882a593Smuzhiyun (mask & IN_ALL_EVENTS));
747*4882a593Smuzhiyun if (ret)
748*4882a593Smuzhiyun goto fput_and_out;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun /* support stacked filesystems */
751*4882a593Smuzhiyun if (path.dentry && path.dentry->d_op) {
752*4882a593Smuzhiyun if (path.dentry->d_op->d_canonical_path) {
753*4882a593Smuzhiyun path.dentry->d_op->d_canonical_path(&path,
754*4882a593Smuzhiyun &alteredpath);
755*4882a593Smuzhiyun canonical_path = &alteredpath;
756*4882a593Smuzhiyun path_put(&path);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun /* inode held in place by reference to path; group by fget on fd */
761*4882a593Smuzhiyun inode = canonical_path->dentry->d_inode;
762*4882a593Smuzhiyun group = f.file->private_data;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /* create/update an inode mark */
765*4882a593Smuzhiyun ret = inotify_update_watch(group, inode, mask);
766*4882a593Smuzhiyun path_put(canonical_path);
767*4882a593Smuzhiyun fput_and_out:
768*4882a593Smuzhiyun fdput(f);
769*4882a593Smuzhiyun return ret;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
SYSCALL_DEFINE2(inotify_rm_watch,int,fd,__s32,wd)772*4882a593Smuzhiyun SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun struct fsnotify_group *group;
775*4882a593Smuzhiyun struct inotify_inode_mark *i_mark;
776*4882a593Smuzhiyun struct fd f;
777*4882a593Smuzhiyun int ret = -EINVAL;
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun f = fdget(fd);
780*4882a593Smuzhiyun if (unlikely(!f.file))
781*4882a593Smuzhiyun return -EBADF;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun /* verify that this is indeed an inotify instance */
784*4882a593Smuzhiyun if (unlikely(f.file->f_op != &inotify_fops))
785*4882a593Smuzhiyun goto out;
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun group = f.file->private_data;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun i_mark = inotify_idr_find(group, wd);
790*4882a593Smuzhiyun if (unlikely(!i_mark))
791*4882a593Smuzhiyun goto out;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun ret = 0;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun fsnotify_destroy_mark(&i_mark->fsn_mark, group);
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /* match ref taken by inotify_idr_find */
798*4882a593Smuzhiyun fsnotify_put_mark(&i_mark->fsn_mark);
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun out:
801*4882a593Smuzhiyun fdput(f);
802*4882a593Smuzhiyun return ret;
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun /*
806*4882a593Smuzhiyun * inotify_user_setup - Our initialization function. Note that we cannot return
807*4882a593Smuzhiyun * error because we have compiled-in VFS hooks. So an (unlikely) failure here
808*4882a593Smuzhiyun * must result in panic().
809*4882a593Smuzhiyun */
inotify_user_setup(void)810*4882a593Smuzhiyun static int __init inotify_user_setup(void)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun BUILD_BUG_ON(IN_ACCESS != FS_ACCESS);
813*4882a593Smuzhiyun BUILD_BUG_ON(IN_MODIFY != FS_MODIFY);
814*4882a593Smuzhiyun BUILD_BUG_ON(IN_ATTRIB != FS_ATTRIB);
815*4882a593Smuzhiyun BUILD_BUG_ON(IN_CLOSE_WRITE != FS_CLOSE_WRITE);
816*4882a593Smuzhiyun BUILD_BUG_ON(IN_CLOSE_NOWRITE != FS_CLOSE_NOWRITE);
817*4882a593Smuzhiyun BUILD_BUG_ON(IN_OPEN != FS_OPEN);
818*4882a593Smuzhiyun BUILD_BUG_ON(IN_MOVED_FROM != FS_MOVED_FROM);
819*4882a593Smuzhiyun BUILD_BUG_ON(IN_MOVED_TO != FS_MOVED_TO);
820*4882a593Smuzhiyun BUILD_BUG_ON(IN_CREATE != FS_CREATE);
821*4882a593Smuzhiyun BUILD_BUG_ON(IN_DELETE != FS_DELETE);
822*4882a593Smuzhiyun BUILD_BUG_ON(IN_DELETE_SELF != FS_DELETE_SELF);
823*4882a593Smuzhiyun BUILD_BUG_ON(IN_MOVE_SELF != FS_MOVE_SELF);
824*4882a593Smuzhiyun BUILD_BUG_ON(IN_UNMOUNT != FS_UNMOUNT);
825*4882a593Smuzhiyun BUILD_BUG_ON(IN_Q_OVERFLOW != FS_Q_OVERFLOW);
826*4882a593Smuzhiyun BUILD_BUG_ON(IN_IGNORED != FS_IN_IGNORED);
827*4882a593Smuzhiyun BUILD_BUG_ON(IN_EXCL_UNLINK != FS_EXCL_UNLINK);
828*4882a593Smuzhiyun BUILD_BUG_ON(IN_ISDIR != FS_ISDIR);
829*4882a593Smuzhiyun BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun BUILD_BUG_ON(HWEIGHT32(ALL_INOTIFY_BITS) != 22);
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark,
834*4882a593Smuzhiyun SLAB_PANIC|SLAB_ACCOUNT);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun inotify_max_queued_events = 16384;
837*4882a593Smuzhiyun init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES] = 128;
838*4882a593Smuzhiyun init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES] = 8192;
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun return 0;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun fs_initcall(inotify_user_setup);
843