Commit 52420392 authored by Eric Paris's avatar Eric Paris

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: default avatarEric Paris <eparis@redhat.com>
parent ff8bcbd0
...@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) ...@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
} }
/* Notify this dentry's parent about a child's events. */ /* Notify this dentry's parent about a child's events. */
void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
{ {
struct dentry *parent; struct dentry *parent;
struct inode *p_inode; struct inode *p_inode;
int ret = 0;
if (!dentry) if (!dentry)
dentry = path->dentry; dentry = path->dentry;
if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
return; return 0;
parent = dget_parent(dentry); parent = dget_parent(dentry);
p_inode = parent->d_inode; p_inode = parent->d_inode;
...@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) ...@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
mask |= FS_EVENT_ON_CHILD; mask |= FS_EVENT_ON_CHILD;
if (path) if (path)
fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
dentry->d_name.name, 0); dentry->d_name.name, 0);
else else
fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
dentry->d_name.name, 0); dentry->d_name.name, 0);
} }
dput(parent); dput(parent);
return ret;
} }
EXPORT_SYMBOL_GPL(__fsnotify_parent); EXPORT_SYMBOL_GPL(__fsnotify_parent);
......
...@@ -26,12 +26,12 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry, ...@@ -26,12 +26,12 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry,
} }
/* Notify this dentry's parent about a child's events. */ /* 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) if (!dentry)
dentry = path->dentry; dentry = path->dentry;
__fsnotify_parent(path, dentry, mask); return __fsnotify_parent(path, dentry, mask);
} }
/* simple call site for access decisions */ /* simple call site for access decisions */
...@@ -40,6 +40,7 @@ static inline int fsnotify_perm(struct file *file, int mask) ...@@ -40,6 +40,7 @@ static inline int fsnotify_perm(struct file *file, int mask)
struct path *path = &file->f_path; struct path *path = &file->f_path;
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
__u32 fsnotify_mask = 0; __u32 fsnotify_mask = 0;
int ret;
if (file->f_mode & FMODE_NONOTIFY) if (file->f_mode & FMODE_NONOTIFY)
return 0; return 0;
...@@ -52,6 +53,10 @@ static inline int fsnotify_perm(struct file *file, int mask) ...@@ -52,6 +53,10 @@ static inline int fsnotify_perm(struct file *file, int mask)
else else
BUG(); BUG();
ret = fsnotify_parent(path, NULL, fsnotify_mask);
if (ret)
return ret;
return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
} }
......
...@@ -304,7 +304,7 @@ struct fsnotify_mark { ...@@ -304,7 +304,7 @@ struct fsnotify_mark {
/* main fsnotify call to send events */ /* main fsnotify call to send events */
extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
const unsigned char *name, u32 cookie); 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_inode_delete(struct inode *inode);
extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
extern u32 fsnotify_get_cookie(void); 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,8 +433,10 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da
return 0; 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) static inline void __fsnotify_inode_delete(struct inode *inode)
{} {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment