Eric Paris | 11637e4 | 2009-12-17 21:24:25 -0500 | [diff] [blame] | 1 | #include <linux/fcntl.h> |
| 2 | #include <linux/fs.h> |
Eric Paris | 52c923d | 2009-12-17 21:24:26 -0500 | [diff] [blame] | 3 | #include <linux/anon_inodes.h> |
Eric Paris | 11637e4 | 2009-12-17 21:24:25 -0500 | [diff] [blame] | 4 | #include <linux/fsnotify_backend.h> |
| 5 | #include <linux/security.h> |
| 6 | #include <linux/syscalls.h> |
| 7 | |
| 8 | #include "fanotify.h" |
| 9 | |
Eric Paris | 52c923d | 2009-12-17 21:24:26 -0500 | [diff] [blame] | 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 */ |
Eric Paris | 11637e4 | 2009-12-17 21:24:25 -0500 | [diff] [blame] | 32 | SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags, |
| 33 | unsigned int, priority) |
| 34 | { |
Eric Paris | 52c923d | 2009-12-17 21:24:26 -0500 | [diff] [blame] | 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; |
Eric Paris | 11637e4 | 2009-12-17 21:24:25 -0500 | [diff] [blame] | 72 | } |
Eric Paris | bbaa416 | 2009-12-17 21:24:26 -0500 | [diff] [blame^] | 73 | |
| 74 | SYSCALL_DEFINE5(fanotify_mark, int, fanotify_fd, unsigned int, flags, |
| 75 | __u64, mask, int, dfd, const char __user *, pathname) |
| 76 | { |
| 77 | return -ENOSYS; |
| 78 | } |