aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/fanotify.h36
-rw-r--r--include/linux/fsnotify.h38
-rw-r--r--include/linux/fsnotify_backend.h26
-rw-r--r--include/linux/sched.h3
5 files changed, 73 insertions, 31 deletions
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 90e3ed3a3144..97319a8fc1e0 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -118,6 +118,7 @@ header-y += eventpoll.h
118header-y += ext2_fs.h 118header-y += ext2_fs.h
119header-y += fadvise.h 119header-y += fadvise.h
120header-y += falloc.h 120header-y += falloc.h
121header-y += fanotify.h
121header-y += fb.h 122header-y += fb.h
122header-y += fcntl.h 123header-y += fcntl.h
123header-y += fd.h 124header-y += fd.h
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 63531a6b4d2a..0f0121467fc4 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -6,18 +6,19 @@
6/* the following events that user-space can register for */ 6/* the following events that user-space can register for */
7#define FAN_ACCESS 0x00000001 /* File was accessed */ 7#define FAN_ACCESS 0x00000001 /* File was accessed */
8#define FAN_MODIFY 0x00000002 /* File was modified */ 8#define FAN_MODIFY 0x00000002 /* File was modified */
9#define FAN_CLOSE_WRITE 0x00000008 /* Unwrittable file closed */ 9#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */
10#define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ 10#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
11#define FAN_OPEN 0x00000020 /* File was opened */ 11#define FAN_OPEN 0x00000020 /* File was opened */
12 12
13#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
14
15/* FIXME currently Q's have no limit.... */
16#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ 13#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
17 14
18#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ 15#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
19#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ 16#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
20 17
18#define FAN_ONDIR 0x40000000 /* event occurred against dir */
19
20#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
21
21/* helper events */ 22/* helper events */
22#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ 23#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
23 24
@@ -25,7 +26,19 @@
25#define FAN_CLOEXEC 0x00000001 26#define FAN_CLOEXEC 0x00000001
26#define FAN_NONBLOCK 0x00000002 27#define FAN_NONBLOCK 0x00000002
27 28
28#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK) 29/* These are NOT bitwise flags. Both bits are used togther. */
30#define FAN_CLASS_NOTIF 0x00000000
31#define FAN_CLASS_CONTENT 0x00000004
32#define FAN_CLASS_PRE_CONTENT 0x00000008
33#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \
34 FAN_CLASS_PRE_CONTENT)
35
36#define FAN_UNLIMITED_QUEUE 0x00000010
37#define FAN_UNLIMITED_MARKS 0x00000020
38
39#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \
40 FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
41 FAN_UNLIMITED_MARKS)
29 42
30/* flags used for fanotify_modify_mark() */ 43/* flags used for fanotify_modify_mark() */
31#define FAN_MARK_ADD 0x00000001 44#define FAN_MARK_ADD 0x00000001
@@ -36,6 +49,10 @@
36#define FAN_MARK_IGNORED_MASK 0x00000020 49#define FAN_MARK_IGNORED_MASK 0x00000020
37#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 50#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
38#define FAN_MARK_FLUSH 0x00000080 51#define FAN_MARK_FLUSH 0x00000080
52#ifdef __KERNEL__
53/* not valid from userspace, only kernel internal */
54#define FAN_MARK_ONDIR 0x00000100
55#endif
39 56
40#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ 57#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
41 FAN_MARK_REMOVE |\ 58 FAN_MARK_REMOVE |\
@@ -43,7 +60,8 @@
43 FAN_MARK_ONLYDIR |\ 60 FAN_MARK_ONLYDIR |\
44 FAN_MARK_MOUNT |\ 61 FAN_MARK_MOUNT |\
45 FAN_MARK_IGNORED_MASK |\ 62 FAN_MARK_IGNORED_MASK |\
46 FAN_MARK_IGNORED_SURV_MODIFY) 63 FAN_MARK_IGNORED_SURV_MODIFY |\
64 FAN_MARK_FLUSH)
47 65
48/* 66/*
49 * All of the events - we build the list by hand so that we can add flags in 67 * All of the events - we build the list by hand so that we can add flags in
@@ -70,10 +88,10 @@
70struct fanotify_event_metadata { 88struct fanotify_event_metadata {
71 __u32 event_len; 89 __u32 event_len;
72 __u32 vers; 90 __u32 vers;
73 __u64 mask; 91 __aligned_u64 mask;
74 __s32 fd; 92 __s32 fd;
75 __s32 pid; 93 __s32 pid;
76} __attribute__ ((packed)); 94};
77 95
78struct fanotify_response { 96struct fanotify_response {
79 __s32 fd; 97 __s32 fd;
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 59d0df43ff9d..5c185fa27089 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -26,12 +26,12 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry,
26} 26}
27 27
28/* Notify this dentry's parent about a child's events. */ 28/* Notify this dentry's parent about a child's events. */
29static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 29static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
30{ 30{
31 if (!dentry) 31 if (!dentry)
32 dentry = path->dentry; 32 dentry = path->dentry;
33 33
34 __fsnotify_parent(path, dentry, mask); 34 return __fsnotify_parent(path, dentry, mask);
35} 35}
36 36
37/* simple call site for access decisions */ 37/* simple call site for access decisions */
@@ -40,6 +40,7 @@ static inline int fsnotify_perm(struct file *file, int mask)
40 struct path *path = &file->f_path; 40 struct path *path = &file->f_path;
41 struct inode *inode = path->dentry->d_inode; 41 struct inode *inode = path->dentry->d_inode;
42 __u32 fsnotify_mask = 0; 42 __u32 fsnotify_mask = 0;
43 int ret;
43 44
44 if (file->f_mode & FMODE_NONOTIFY) 45 if (file->f_mode & FMODE_NONOTIFY)
45 return 0; 46 return 0;
@@ -52,6 +53,10 @@ static inline int fsnotify_perm(struct file *file, int mask)
52 else 53 else
53 BUG(); 54 BUG();
54 55
56 ret = fsnotify_parent(path, NULL, fsnotify_mask);
57 if (ret)
58 return ret;
59
55 return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 60 return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
56} 61}
57 62
@@ -93,8 +98,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
93 old_dir_mask |= FS_DN_RENAME; 98 old_dir_mask |= FS_DN_RENAME;
94 99
95 if (isdir) { 100 if (isdir) {
96 old_dir_mask |= FS_IN_ISDIR; 101 old_dir_mask |= FS_ISDIR;
97 new_dir_mask |= FS_IN_ISDIR; 102 new_dir_mask |= FS_ISDIR;
98 } 103 }
99 104
100 fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); 105 fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie);
@@ -132,7 +137,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
132 __u32 mask = FS_DELETE; 137 __u32 mask = FS_DELETE;
133 138
134 if (isdir) 139 if (isdir)
135 mask |= FS_IN_ISDIR; 140 mask |= FS_ISDIR;
136 141
137 fsnotify_parent(NULL, dentry, mask); 142 fsnotify_parent(NULL, dentry, mask);
138} 143}
@@ -174,7 +179,7 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
174 */ 179 */
175static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) 180static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
176{ 181{
177 __u32 mask = (FS_CREATE | FS_IN_ISDIR); 182 __u32 mask = (FS_CREATE | FS_ISDIR);
178 struct inode *d_inode = dentry->d_inode; 183 struct inode *d_inode = dentry->d_inode;
179 184
180 audit_inode_child(dentry, inode); 185 audit_inode_child(dentry, inode);
@@ -192,7 +197,7 @@ static inline void fsnotify_access(struct file *file)
192 __u32 mask = FS_ACCESS; 197 __u32 mask = FS_ACCESS;
193 198
194 if (S_ISDIR(inode->i_mode)) 199 if (S_ISDIR(inode->i_mode))
195 mask |= FS_IN_ISDIR; 200 mask |= FS_ISDIR;
196 201
197 if (!(file->f_mode & FMODE_NONOTIFY)) { 202 if (!(file->f_mode & FMODE_NONOTIFY)) {
198 fsnotify_parent(path, NULL, mask); 203 fsnotify_parent(path, NULL, mask);
@@ -210,7 +215,7 @@ static inline void fsnotify_modify(struct file *file)
210 __u32 mask = FS_MODIFY; 215 __u32 mask = FS_MODIFY;
211 216
212 if (S_ISDIR(inode->i_mode)) 217 if (S_ISDIR(inode->i_mode))
213 mask |= FS_IN_ISDIR; 218 mask |= FS_ISDIR;
214 219
215 if (!(file->f_mode & FMODE_NONOTIFY)) { 220 if (!(file->f_mode & FMODE_NONOTIFY)) {
216 fsnotify_parent(path, NULL, mask); 221 fsnotify_parent(path, NULL, mask);
@@ -228,12 +233,13 @@ static inline void fsnotify_open(struct file *file)
228 __u32 mask = FS_OPEN; 233 __u32 mask = FS_OPEN;
229 234
230 if (S_ISDIR(inode->i_mode)) 235 if (S_ISDIR(inode->i_mode))
231 mask |= FS_IN_ISDIR; 236 mask |= FS_ISDIR;
232 237
233 if (!(file->f_mode & FMODE_NONOTIFY)) { 238 /* FMODE_NONOTIFY must never be set from user */
234 fsnotify_parent(path, NULL, mask); 239 file->f_mode &= ~FMODE_NONOTIFY;
235 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 240
236 } 241 fsnotify_parent(path, NULL, mask);
242 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
237} 243}
238 244
239/* 245/*
@@ -247,7 +253,7 @@ static inline void fsnotify_close(struct file *file)
247 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; 253 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
248 254
249 if (S_ISDIR(inode->i_mode)) 255 if (S_ISDIR(inode->i_mode))
250 mask |= FS_IN_ISDIR; 256 mask |= FS_ISDIR;
251 257
252 if (!(file->f_mode & FMODE_NONOTIFY)) { 258 if (!(file->f_mode & FMODE_NONOTIFY)) {
253 fsnotify_parent(path, NULL, mask); 259 fsnotify_parent(path, NULL, mask);
@@ -264,7 +270,7 @@ static inline void fsnotify_xattr(struct dentry *dentry)
264 __u32 mask = FS_ATTRIB; 270 __u32 mask = FS_ATTRIB;
265 271
266 if (S_ISDIR(inode->i_mode)) 272 if (S_ISDIR(inode->i_mode))
267 mask |= FS_IN_ISDIR; 273 mask |= FS_ISDIR;
268 274
269 fsnotify_parent(NULL, dentry, mask); 275 fsnotify_parent(NULL, dentry, mask);
270 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 276 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
@@ -299,7 +305,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
299 305
300 if (mask) { 306 if (mask) {
301 if (S_ISDIR(inode->i_mode)) 307 if (S_ISDIR(inode->i_mode))
302 mask |= FS_IN_ISDIR; 308 mask |= FS_ISDIR;
303 309
304 fsnotify_parent(NULL, dentry, mask); 310 fsnotify_parent(NULL, dentry, mask);
305 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 311 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index e40190d16878..0a68f924f06f 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -45,7 +45,7 @@
45#define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ 45#define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */
46 46
47#define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ 47#define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */
48#define FS_IN_ISDIR 0x40000000 /* event occurred against dir */ 48#define FS_ISDIR 0x40000000 /* event occurred against dir */
49#define FS_IN_ONESHOT 0x80000000 /* only send event once */ 49#define FS_IN_ONESHOT 0x80000000 /* only send event once */
50 50
51#define FS_DN_RENAME 0x10000000 /* file renamed */ 51#define FS_DN_RENAME 0x10000000 /* file renamed */
@@ -64,13 +64,15 @@
64 64
65#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) 65#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
66 66
67#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM)
68
67#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ 69#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
68 FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ 70 FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \
69 FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ 71 FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \
70 FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ 72 FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \
71 FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ 73 FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
72 FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \ 74 FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \
73 FS_IN_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ 75 FS_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \
74 FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) 76 FS_DN_MULTISHOT | FS_EVENT_ON_CHILD)
75 77
76struct fsnotify_group; 78struct fsnotify_group;
@@ -129,6 +131,14 @@ struct fsnotify_group {
129 wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */ 131 wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */
130 unsigned int q_len; /* events on the queue */ 132 unsigned int q_len; /* events on the queue */
131 unsigned int max_events; /* maximum events allowed on the list */ 133 unsigned int max_events; /* maximum events allowed on the list */
134 /*
135 * Valid fsnotify group priorities. Events are send in order from highest
136 * priority to lowest priority. We default to the lowest priority.
137 */
138 #define FS_PRIO_0 0 /* normal notifiers, no permissions */
139 #define FS_PRIO_1 1 /* fanotify content based access control */
140 #define FS_PRIO_2 2 /* fanotify pre-content access */
141 unsigned int priority;
132 142
133 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ 143 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */
134 spinlock_t mark_lock; /* protect marks_list */ 144 spinlock_t mark_lock; /* protect marks_list */
@@ -159,6 +169,8 @@ struct fsnotify_group {
159 bool bypass_perm; /* protected by access_mutex */ 169 bool bypass_perm; /* protected by access_mutex */
160#endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ 170#endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
161 int f_flags; 171 int f_flags;
172 unsigned int max_marks;
173 struct user_struct *user;
162 } fanotify_data; 174 } fanotify_data;
163#endif /* CONFIG_FANOTIFY */ 175#endif /* CONFIG_FANOTIFY */
164 }; 176 };
@@ -275,8 +287,8 @@ struct fsnotify_mark {
275 struct fsnotify_inode_mark i; 287 struct fsnotify_inode_mark i;
276 struct fsnotify_vfsmount_mark m; 288 struct fsnotify_vfsmount_mark m;
277 }; 289 };
278 __u32 ignored_mask; /* events types to ignore */
279 struct list_head free_g_list; /* tmp list used when freeing this mark */ 290 struct list_head free_g_list; /* tmp list used when freeing this mark */
291 __u32 ignored_mask; /* events types to ignore */
280#define FSNOTIFY_MARK_FLAG_INODE 0x01 292#define FSNOTIFY_MARK_FLAG_INODE 0x01
281#define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 293#define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02
282#define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04 294#define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04
@@ -294,7 +306,7 @@ struct fsnotify_mark {
294/* main fsnotify call to send events */ 306/* main fsnotify call to send events */
295extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, 307extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
296 const unsigned char *name, u32 cookie); 308 const unsigned char *name, u32 cookie);
297extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); 309extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask);
298extern void __fsnotify_inode_delete(struct inode *inode); 310extern void __fsnotify_inode_delete(struct inode *inode);
299extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 311extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
300extern u32 fsnotify_get_cookie(void); 312extern u32 fsnotify_get_cookie(void);
@@ -423,8 +435,10 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da
423 return 0; 435 return 0;
424} 436}
425 437
426static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 438static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
427{} 439{
440 return 0;
441}
428 442
429static inline void __fsnotify_inode_delete(struct inode *inode) 443static inline void __fsnotify_inode_delete(struct inode *inode)
430{} 444{}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f53cdf216cef..d0036e52a24a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -672,6 +672,9 @@ struct user_struct {
672 atomic_t inotify_watches; /* How many inotify watches does this user have? */ 672 atomic_t inotify_watches; /* How many inotify watches does this user have? */
673 atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ 673 atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
674#endif 674#endif
675#ifdef CONFIG_FANOTIFY
676 atomic_t fanotify_listeners;
677#endif
675#ifdef CONFIG_EPOLL 678#ifdef CONFIG_EPOLL
676 atomic_t epoll_watches; /* The number of file descriptors currently watched */ 679 atomic_t epoll_watches; /* The number of file descriptors currently watched */
677#endif 680#endif