aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-28 17:21:56 -0400
committerEric Paris <eparis@redhat.com>2010-10-28 17:22:13 -0400
commit52420392c81c8712f555e6bcd116d8bd214ce43a (patch)
tree372d23bba71ee687ff5adf5b83d3fd0706e19927
parentff8bcbd03da881bf1171910c6c07d44bd3c0a234 (diff)
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 <eparis@redhat.com>
-rw-r--r--fs/notify/fsnotify.c15
-rw-r--r--include/linux/fsnotify.h9
-rw-r--r--include/linux/fsnotify_backend.h8
3 files changed, 21 insertions, 11 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 57ecadd85abf..20dc218707ca 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
84} 84}
85 85
86/* Notify this dentry's parent about a child's events. */ 86/* Notify this dentry's parent about a child's events. */
87void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 87int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
88{ 88{
89 struct dentry *parent; 89 struct dentry *parent;
90 struct inode *p_inode; 90 struct inode *p_inode;
91 int ret = 0;
91 92
92 if (!dentry) 93 if (!dentry)
93 dentry = path->dentry; 94 dentry = path->dentry;
94 95
95 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) 96 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
96 return; 97 return 0;
97 98
98 parent = dget_parent(dentry); 99 parent = dget_parent(dentry);
99 p_inode = parent->d_inode; 100 p_inode = parent->d_inode;
@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
106 mask |= FS_EVENT_ON_CHILD; 107 mask |= FS_EVENT_ON_CHILD;
107 108
108 if (path) 109 if (path)
109 fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 110 ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
110 dentry->d_name.name, 0); 111 dentry->d_name.name, 0);
111 else 112 else
112 fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 113 ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
113 dentry->d_name.name, 0); 114 dentry->d_name.name, 0);
114 } 115 }
115 116
116 dput(parent); 117 dput(parent);
118
119 return ret;
117} 120}
118EXPORT_SYMBOL_GPL(__fsnotify_parent); 121EXPORT_SYMBOL_GPL(__fsnotify_parent);
119 122
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 59d0df43ff9d..5059faacceab 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
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 026892187c83..b37f3a71a9dc 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -304,7 +304,7 @@ struct fsnotify_mark {
304/* main fsnotify call to send events */ 304/* main fsnotify call to send events */
305extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, 305extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
306 const unsigned char *name, u32 cookie); 306 const unsigned char *name, u32 cookie);
307extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); 307extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask);
308extern void __fsnotify_inode_delete(struct inode *inode); 308extern void __fsnotify_inode_delete(struct inode *inode);
309extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 309extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
310extern u32 fsnotify_get_cookie(void); 310extern u32 fsnotify_get_cookie(void);
@@ -433,8 +433,10 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da
433 return 0; 433 return 0;
434} 434}
435 435
436static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 436static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
437{} 437{
438 return 0;
439}
438 440
439static inline void __fsnotify_inode_delete(struct inode *inode) 441static inline void __fsnotify_inode_delete(struct inode *inode)
440{} 442{}