diff options
| author | Eric Paris <eparis@redhat.com> | 2010-10-28 17:21:56 -0400 |
|---|---|---|
| committer | Eric Paris <eparis@redhat.com> | 2010-10-28 17:22:13 -0400 |
| commit | 52420392c81c8712f555e6bcd116d8bd214ce43a (patch) | |
| tree | 372d23bba71ee687ff5adf5b83d3fd0706e19927 | |
| parent | ff8bcbd03da881bf1171910c6c07d44bd3c0a234 (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.c | 15 | ||||
| -rw-r--r-- | include/linux/fsnotify.h | 9 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 8 |
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. */ |
| 87 | void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | 87 | int __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 | } |
| 118 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 121 | EXPORT_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. */ |
| 29 | static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | 29 | static 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 */ |
| 305 | extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 305 | extern 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); |
| 307 | extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); | 307 | extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); |
| 308 | extern void __fsnotify_inode_delete(struct inode *inode); | 308 | extern void __fsnotify_inode_delete(struct inode *inode); |
| 309 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); | 309 | extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); |
| 310 | extern u32 fsnotify_get_cookie(void); | 310 | extern 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 | ||
| 436 | static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | 436 | static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) |
| 437 | {} | 437 | { |
| 438 | return 0; | ||
| 439 | } | ||
| 438 | 440 | ||
| 439 | static inline void __fsnotify_inode_delete(struct inode *inode) | 441 | static inline void __fsnotify_inode_delete(struct inode *inode) |
| 440 | {} | 442 | {} |
