From 9343919c1495b085a4a1cf4cbada8d7888daf099 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fanotify: allow fanotify to be built We disabled the ability to build fanotify in commit 7c5347733dcc4ba0ba. This reverts that commit and allows people to build fanotify. Signed-off-by: Eric Paris --- include/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 90e3ed3a314..97319a8fc1e 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -118,6 +118,7 @@ header-y += eventpoll.h header-y += ext2_fs.h header-y += fadvise.h header-y += falloc.h +header-y += fanotify.h header-y += fb.h header-y += fcntl.h header-y += fd.h -- cgit v1.2.3 From 6ad2d4e3e97ee4bfde0b45e8dfe37911330fc4aa Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fsnotify: implement ordering between notifiers fanotify needs to be able to specify that some groups get events before others. They use this idea to make sure that a hierarchical storage manager gets access to files before programs which actually use them. This is purely infrastructure. Everything will have a priority of 0, but the infrastructure will exist for it to be non-zero. Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index e40190d1687..82532953416 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -129,6 +129,14 @@ struct fsnotify_group { wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */ unsigned int q_len; /* events on the queue */ unsigned int max_events; /* maximum events allowed on the list */ + /* + * Valid fsnotify group priorities. Events are send in order from highest + * priority to lowest priority. We default to the lowest priority. + */ + #define FS_PRIO_0 0 /* normal notifiers, no permissions */ + #define FS_PRIO_1 1 /* fanotify content based access control */ + #define FS_PRIO_2 2 /* fanotify pre-content access */ + unsigned int priority; /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ spinlock_t mark_lock; /* protect marks_list */ -- cgit v1.2.3 From 4231a23530a30e86eb32fbe869bbef1b3e54d5aa Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fanotify: implement fanotify listener ordering The fanotify listeners needs to be able to specify what types of operations they are going to perform so they can be ordered appropriately between other listeners doing other types of operations. They need this to be able to make sure that things like hierarchichal storage managers will get access to inodes before processes which need the data. This patch defines 3 possible uses which groups must indicate in the fanotify_init() flags. FAN_CLASS_PRE_CONTENT FAN_CLASS_CONTENT FAN_CLASS_NOTIF Groups will receive notification in that order. The order between 2 groups in the same class is undeterministic. FAN_CLASS_PRE_CONTENT is intended to be used by listeners which need access to the inode before they are certain that the inode contains it's final data. A hierarchical storage manager should choose to use this class. FAN_CLASS_CONTENT is intended to be used by listeners which need access to the inode after it contains its intended contents. This would be the appropriate level for an AV solution or document control system. FAN_CLASS_NOTIF is intended for normal async notification about access, much the same as inotify and dnotify. Syncronous permissions events are not permitted at this class. Signed-off-by: Eric Paris --- include/linux/fanotify.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 63531a6b4d2..2c89ce7b644 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -25,7 +25,16 @@ #define FAN_CLOEXEC 0x00000001 #define FAN_NONBLOCK 0x00000002 -#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK) +/* These are NOT bitwise flags. Both bits are used togther. */ +#define FAN_CLASS_NOTIF 0x00000000 +#define FAN_CLASS_CONTENT 0x00000004 +#define FAN_CLASS_PRE_CONTENT 0x00000008 + +#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ + FAN_CLASS_PRE_CONTENT) + +#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ + FAN_ALL_CLASS_BITS) /* flags used for fanotify_modify_mark() */ #define FAN_MARK_ADD 0x00000001 -- cgit v1.2.3 From 2868201965419b9011f3f07fd80e765181343cb1 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fanotify: use __aligned_u64 in fanotify userspace metadata Currently the userspace struct exposed by fanotify uses __attribute__((packed)) to make sure that alignment works on multiarch platforms. Since this causes a severe performance penalty on some platforms we are going to switch to using explicit alignment notation on the 64bit values so we don't have to use 'packed' Signed-off-by: Eric Paris --- include/linux/fanotify.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 2c89ce7b644..8a621c1a099 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -79,10 +79,10 @@ struct fanotify_event_metadata { __u32 event_len; __u32 vers; - __u64 mask; + __aligned_u64 mask; __s32 fd; __s32 pid; -} __attribute__ ((packed)); +}; struct fanotify_response { __s32 fd; -- cgit v1.2.3 From ff8bcbd03da881bf1171910c6c07d44bd3c0a234 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fsnotify: correctly handle return codes from listeners When fsnotify groups return errors they are ignored. For permissions events these should be passed back up the stack, but for most events these should continue to be ignored. Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 82532953416..026892187c8 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -64,6 +64,8 @@ #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) +#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM) + #define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ -- cgit v1.2.3 From 52420392c81c8712f555e6bcd116d8bd214ce43a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:56 -0400 Subject: fsnotify: call fsnotify_parent in perm events fsnotify perm events do not call fsnotify parent. That means you cannot register a perm event on a directory and enforce permissions on all inodes in that directory. This patch fixes that situation. Signed-off-by: Eric Paris --- include/linux/fsnotify.h | 9 +++++++-- include/linux/fsnotify_backend.h | 8 +++++--- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 59d0df43ff9..5059faaccea 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -26,12 +26,12 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry, } /* Notify this dentry's parent about a child's events. */ -static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) +static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) { if (!dentry) dentry = path->dentry; - __fsnotify_parent(path, dentry, mask); + return __fsnotify_parent(path, dentry, mask); } /* simple call site for access decisions */ @@ -40,6 +40,7 @@ static inline int fsnotify_perm(struct file *file, int mask) struct path *path = &file->f_path; struct inode *inode = path->dentry->d_inode; __u32 fsnotify_mask = 0; + int ret; if (file->f_mode & FMODE_NONOTIFY) return 0; @@ -52,6 +53,10 @@ static inline int fsnotify_perm(struct file *file, int mask) else BUG(); + ret = fsnotify_parent(path, NULL, fsnotify_mask); + if (ret) + return ret; + return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 026892187c8..b37f3a71a9d 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -304,7 +304,7 @@ struct fsnotify_mark { /* main fsnotify call to send events */ extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const unsigned char *name, u32 cookie); -extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); +extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); extern void __fsnotify_inode_delete(struct inode *inode); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern u32 fsnotify_get_cookie(void); @@ -433,8 +433,10 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da return 0; } -static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) -{} +static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) +{ + return 0; +} static inline void __fsnotify_inode_delete(struct inode *inode) {} -- cgit v1.2.3 From bbf2aba50f6ed7c8dd53623fa1437b539928ac39 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:57 -0400 Subject: fanotify: allow userspace to flush all marks fanotify is supposed to be able to flush all marks. This is mostly useful for the AV community to flush all cached decisions on a security policy change. This functionality has existed in the kernel but wasn't correctly exposed to userspace. Signed-off-by: Eric Paris --- include/linux/fanotify.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 8a621c1a099..a97c96d28c0 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -52,7 +52,8 @@ FAN_MARK_ONLYDIR |\ FAN_MARK_MOUNT |\ FAN_MARK_IGNORED_MASK |\ - FAN_MARK_IGNORED_SURV_MODIFY) + FAN_MARK_IGNORED_SURV_MODIFY |\ + FAN_MARK_FLUSH) /* * All of the events - we build the list by hand so that we can add flags in -- cgit v1.2.3 From 2529a0df0f64dab1f60ae08e038b89c53a6b4c02 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:57 -0400 Subject: fsnotify: implement a default maximum queue depth Currently fanotify has no maximum queue depth. Since fanotify is CAP_SYS_ADMIN only this does not pose a normal user DoS issue, but it certianly is possible that an fanotify listener which can't keep up could OOM the box. This patch implements a default 16k depth. This is the same default depth used by inotify, but given fanotify's better queue merging in many situations this queue will contain many additional useful events by comparison. Signed-off-by: Eric Paris --- include/linux/fanotify.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index a97c96d28c0..ed479b6fef7 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -12,7 +12,6 @@ #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ -/* FIXME currently Q's have no limit.... */ #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ -- cgit v1.2.3 From 5dd03f55fd2f21916ce248bb2e68bbfb39d94fe5 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:57 -0400 Subject: fanotify: allow userspace to override max queue depth fanotify has a defualt max queue depth. This patch allows processes which explicitly request it to have an 'unlimited' queue depth. These processes need to be very careful to make sure they cannot fall far enough behind that they OOM the box. Thus this flag is gated on CAP_SYS_ADMIN. Signed-off-by: Eric Paris --- include/linux/fanotify.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index ed479b6fef7..e37f559c95e 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -28,12 +28,13 @@ #define FAN_CLASS_NOTIF 0x00000000 #define FAN_CLASS_CONTENT 0x00000004 #define FAN_CLASS_PRE_CONTENT 0x00000008 - #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ FAN_CLASS_PRE_CONTENT) +#define FAN_UNLIMITED_QUEUE 0x00000010 + #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ - FAN_ALL_CLASS_BITS) + FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE) /* flags used for fanotify_modify_mark() */ #define FAN_MARK_ADD 0x00000001 -- cgit v1.2.3 From e7099d8a5a34d2876908a9fab4952dabdcfc5909 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:57 -0400 Subject: fanotify: limit the number of marks in a single fanotify group There is currently no limit on the number of marks a given fanotify group can have. Since fanotify is gated on CAP_SYS_ADMIN this was not seen as a serious DoS threat. This patch implements a default of 8192, the same as inotify to work towards removing the CAP_SYS_ADMIN gating and eliminating the default DoS'able status. Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index b37f3a71a9d..49ceed6e92b 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -169,6 +169,7 @@ struct fsnotify_group { bool bypass_perm; /* protected by access_mutex */ #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ int f_flags; + unsigned int max_marks; } fanotify_data; #endif /* CONFIG_FANOTIFY */ }; -- cgit v1.2.3 From ac7e22dcfafd04c842a02057afd6541c1d613ef9 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:58 -0400 Subject: fanotify: allow userspace to override max marks Some fanotify groups, especially those like AV scanners, will need to place lots of marks, particularly ignore marks. Since ignore marks do not pin inodes in cache and are cleared if the inode is removed from core (usually under memory pressure) we expose an interface for listeners, with CAP_SYS_ADMIN, to override the maximum number of marks and be allowed to set and 'unlimited' number of marks. Programs which make use of this feature will be able to OOM a machine. Signed-off-by: Eric Paris --- include/linux/fanotify.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index e37f559c95e..7592a366a57 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -32,9 +32,11 @@ FAN_CLASS_PRE_CONTENT) #define FAN_UNLIMITED_QUEUE 0x00000010 +#define FAN_UNLIMITED_MARKS 0x00000020 #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ - FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE) + FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ + FAN_UNLIMITED_MARKS) /* flags used for fanotify_modify_mark() */ #define FAN_MARK_ADD 0x00000001 -- cgit v1.2.3 From 4afeff8505cb8a38e36c1ef2bd3447c4b8f87367 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:58 -0400 Subject: fanotify: limit number of listeners per user fanotify currently has no limit on the number of listeners a given user can have open. This patch limits the total number of listeners per user to 128. This is the same as the inotify default limit. Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 1 + include/linux/sched.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 49ceed6e92b..4366f458a86 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -170,6 +170,7 @@ struct fsnotify_group { #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ int f_flags; unsigned int max_marks; + struct user_struct *user; } fanotify_data; #endif /* CONFIG_FANOTIFY */ }; diff --git a/include/linux/sched.h b/include/linux/sched.h index be7adb7588e..6f420baf37c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -672,6 +672,9 @@ struct user_struct { atomic_t inotify_watches; /* How many inotify watches does this user have? */ atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ #endif +#ifdef CONFIG_FANOTIFY + atomic_t fanotify_listeners; +#endif #ifdef CONFIG_EPOLL atomic_t epoll_watches; /* The number of file descriptors currently watched */ #endif -- cgit v1.2.3 From b29866aab8489487f11cc4506590ac31bdbae22a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:58 -0400 Subject: fsnotify: rename FS_IN_ISDIR to FS_ISDIR The _IN_ in the naming is reserved for flags only used by inotify. Since I am about to use this flag for fanotify rename it to be generic like the rest. Signed-off-by: Eric Paris --- include/linux/fsnotify.h | 20 ++++++++++---------- include/linux/fsnotify_backend.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 5059faaccea..ecb43b33d18 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -98,8 +98,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, old_dir_mask |= FS_DN_RENAME; if (isdir) { - old_dir_mask |= FS_IN_ISDIR; - new_dir_mask |= FS_IN_ISDIR; + old_dir_mask |= FS_ISDIR; + new_dir_mask |= FS_ISDIR; } fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); @@ -137,7 +137,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) __u32 mask = FS_DELETE; if (isdir) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; fsnotify_parent(NULL, dentry, mask); } @@ -179,7 +179,7 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct */ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) { - __u32 mask = (FS_CREATE | FS_IN_ISDIR); + __u32 mask = (FS_CREATE | FS_ISDIR); struct inode *d_inode = dentry->d_inode; audit_inode_child(dentry, inode); @@ -197,7 +197,7 @@ static inline void fsnotify_access(struct file *file) __u32 mask = FS_ACCESS; if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { fsnotify_parent(path, NULL, mask); @@ -215,7 +215,7 @@ static inline void fsnotify_modify(struct file *file) __u32 mask = FS_MODIFY; if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { fsnotify_parent(path, NULL, mask); @@ -233,7 +233,7 @@ static inline void fsnotify_open(struct file *file) __u32 mask = FS_OPEN; if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { fsnotify_parent(path, NULL, mask); @@ -252,7 +252,7 @@ static inline void fsnotify_close(struct file *file) __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; if (!(file->f_mode & FMODE_NONOTIFY)) { fsnotify_parent(path, NULL, mask); @@ -269,7 +269,7 @@ static inline void fsnotify_xattr(struct dentry *dentry) __u32 mask = FS_ATTRIB; if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; fsnotify_parent(NULL, dentry, mask); fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); @@ -304,7 +304,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) if (mask) { if (S_ISDIR(inode->i_mode)) - mask |= FS_IN_ISDIR; + mask |= FS_ISDIR; fsnotify_parent(NULL, dentry, mask); fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 4366f458a86..b36041e9cd3 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -45,7 +45,7 @@ #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ -#define FS_IN_ISDIR 0x40000000 /* event occurred against dir */ +#define FS_ISDIR 0x40000000 /* event occurred against dir */ #define FS_IN_ONESHOT 0x80000000 /* only send event once */ #define FS_DN_RENAME 0x10000000 /* file renamed */ @@ -72,7 +72,7 @@ FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \ - FS_IN_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ + FS_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) struct fsnotify_group; -- cgit v1.2.3 From 8fcd65280abc4699510f1853ede31f43e8a3783a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Oct 2010 17:21:59 -0400 Subject: fanotify: ignore events on directories unless specifically requested fanotify has a very limited number of events it sends on directories. The usefulness of these events is yet to be seen and still we send them. This is particularly painful for mount marks where one might receive many of these useless events. As such this patch will drop events on IS_DIR() inodes unless they were explictly requested with FAN_ON_DIR. This means that a mark on a directory without FAN_EVENT_ON_CHILD or FAN_ON_DIR is meaningless and will result in no events ever (although it will still be allowed since detecting it is hard) Signed-off-by: Eric Paris --- include/linux/fanotify.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 7592a366a57..5e0400a80c3 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -10,13 +10,15 @@ #define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ #define FAN_OPEN 0x00000020 /* File was opened */ -#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ - #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ +#define FAN_ONDIR 0x40000000 /* event occurred against dir */ + +#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ + /* helper events */ #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ @@ -47,6 +49,10 @@ #define FAN_MARK_IGNORED_MASK 0x00000020 #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 #define FAN_MARK_FLUSH 0x00000080 +#ifdef __KERNEL__ +/* not valid from userspace, only kernel internal */ +#define FAN_MARK_ONDIR 0x00000100 +#endif #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ FAN_MARK_REMOVE |\ -- cgit v1.2.3 From 50e4a98914de13c6f38f50fd1afa06e2c18b3cf7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 28 Oct 2010 17:21:59 -0400 Subject: fanotify: Fix FAN_CLOSE comments The comments for FAN_CLOSE_WRITE and FAN_CLOSE_NOWRITE do not match FS_CLOSE_WRITE and FS_CLOSE_NOWRITE, respectively. WRITE is for writable files while NOWRITE is for non-writable files. Signed-off-by: Stefan Hajnoczi Signed-off-by: Eric Paris --- include/linux/fanotify.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h index 5e0400a80c3..0f0121467fc 100644 --- a/include/linux/fanotify.h +++ b/include/linux/fanotify.h @@ -6,8 +6,8 @@ /* the following events that user-space can register for */ #define FAN_ACCESS 0x00000001 /* File was accessed */ #define FAN_MODIFY 0x00000002 /* File was modified */ -#define FAN_CLOSE_WRITE 0x00000008 /* Unwrittable file closed */ -#define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ +#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */ +#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ #define FAN_OPEN 0x00000020 /* File was opened */ #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ -- cgit v1.2.3 From d8c0fca68da25ca3df534dfb12ce628675c828e4 Mon Sep 17 00:00:00 2001 From: Richard Kennedy Date: Thu, 28 Oct 2010 17:21:59 -0400 Subject: fsnotify: remove alignment padding from fsnotify_mark on 64 bit builds Reorder struct fsnotfiy_mark to remove 8 bytes of alignment padding on 64 bit builds. Shrinks fsnotfiy_mark to 128 bytes allowing more objects per slab in its kmem_cache and reduces the number of cachelines needed for each structure. Signed-off-by: Richard Kennedy Cc: Eric Paris Signed-off-by: Andrew Morton Signed-off-by: Eric Paris --- include/linux/fsnotify_backend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index b36041e9cd3..0a68f924f06 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -287,8 +287,8 @@ struct fsnotify_mark { struct fsnotify_inode_mark i; struct fsnotify_vfsmount_mark m; }; - __u32 ignored_mask; /* events types to ignore */ struct list_head free_g_list; /* tmp list used when freeing this mark */ + __u32 ignored_mask; /* events types to ignore */ #define FSNOTIFY_MARK_FLAG_INODE 0x01 #define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 #define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04 -- cgit v1.2.3 From 6bff7eccb0d9bdef4123aad5399e73cbc26683a6 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Fri, 29 Oct 2010 12:02:17 +0200 Subject: Ensure FMODE_NONOTIFY is not set by userspace In fsnotify_open() ensure that FMODE_NONOTIFY is never set by userspace. Also always call fsnotify_parent and fsnotify. Signed-off-by: Lino Sanfilippo Signed-off-by: Eric Paris --- include/linux/fsnotify.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index ecb43b33d18..5c185fa2708 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -235,10 +235,11 @@ static inline void fsnotify_open(struct file *file) if (S_ISDIR(inode->i_mode)) mask |= FS_ISDIR; - if (!(file->f_mode & FMODE_NONOTIFY)) { - fsnotify_parent(path, NULL, mask); - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); - } + /* FMODE_NONOTIFY must never be set from user */ + file->f_mode &= ~FMODE_NONOTIFY; + + fsnotify_parent(path, NULL, mask); + fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); } /* -- cgit v1.2.3