]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/notify/fanotify/fanotify_user.c
67c0b5e4a4886b4838a6b026bf955c343bd3e49e
[net-next-2.6.git] / fs / notify / fanotify / fanotify_user.c
1 #include <linux/fcntl.h>
2 #include <linux/fs.h>
3 #include <linux/anon_inodes.h>
4 #include <linux/fsnotify_backend.h>
5 #include <linux/security.h>
6 #include <linux/syscalls.h>
7
8 #include "fanotify.h"
9
10 static int fanotify_release(struct inode *ignored, struct file *file)
11 {
12         struct fsnotify_group *group = file->private_data;
13
14         pr_debug("%s: file=%p group=%p\n", __func__, file, group);
15
16         /* matches the fanotify_init->fsnotify_alloc_group */
17         fsnotify_put_group(group);
18
19         return 0;
20 }
21
22 static const struct file_operations fanotify_fops = {
23         .poll           = NULL,
24         .read           = NULL,
25         .fasync         = NULL,
26         .release        = fanotify_release,
27         .unlocked_ioctl = NULL,
28         .compat_ioctl   = NULL,
29 };
30
31 /* fanotify syscalls */
32 SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
33                 unsigned int, priority)
34 {
35         struct fsnotify_group *group;
36         int f_flags, fd;
37
38         pr_debug("%s: flags=%d event_f_flags=%d priority=%d\n",
39                 __func__, flags, event_f_flags, priority);
40
41         if (event_f_flags)
42                 return -EINVAL;
43         if (priority)
44                 return -EINVAL;
45
46         if (!capable(CAP_SYS_ADMIN))
47                 return -EACCES;
48
49         if (flags & ~FAN_ALL_INIT_FLAGS)
50                 return -EINVAL;
51
52         f_flags = (O_RDONLY | FMODE_NONOTIFY);
53         if (flags & FAN_CLOEXEC)
54                 f_flags |= O_CLOEXEC;
55         if (flags & FAN_NONBLOCK)
56                 f_flags |= O_NONBLOCK;
57
58         /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
59         group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
60         if (IS_ERR(group))
61                 return PTR_ERR(group);
62
63         fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
64         if (fd < 0)
65                 goto out_put_group;
66
67         return fd;
68
69 out_put_group:
70         fsnotify_put_group(group);
71         return fd;
72 }