Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52420392 authored by Eric Paris's avatar Eric Paris
Browse files

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
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
}

/* 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 inode *p_inode;
	int ret = 0;

	if (!dentry)
		dentry = path->dentry;

	if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
		return;
		return 0;

	parent = dget_parent(dentry);
	p_inode = parent->d_inode;
@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
		mask |= FS_EVENT_ON_CHILD;

		if (path)
			fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
			ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
				       dentry->d_name.name, 0);
		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);
	}

	dput(parent);

	return ret;
}
EXPORT_SYMBOL_GPL(__fsnotify_parent);

+7 −2
Original line number Diff line number Diff line
@@ -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);
}

+5 −3
Original line number Diff line number Diff line
@@ -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)
{}