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

Commit e8e96157 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds
Browse files

fuse: clean up execute permission checking



Define a new function fuse_refresh_attributes() that conditionally refreshes
the attributes based on the validity timeout.

In fuse_permission() only refresh the attributes for checking the execute bits
if necessary.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c9c9d7df
Loading
Loading
Loading
Loading
+31 −18
Original line number Diff line number Diff line
@@ -694,6 +694,20 @@ static int fuse_do_getattr(struct inode *inode)
	return err;
}

/*
 * Check if attributes are still valid, and if not send a GETATTR
 * request to refresh them.
 */
static int fuse_refresh_attributes(struct inode *inode)
{
	struct fuse_inode *fi = get_fuse_inode(inode);

	if (fi->i_time < get_jiffies_64())
		return fuse_do_getattr(inode);
	else
		return 0;
}

/*
 * Calling into a user-controlled filesystem gives the filesystem
 * daemon ptrace-like capabilities over the requester process.  This
@@ -770,7 +784,6 @@ static int fuse_access(struct inode *inode, int mask)
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
	struct fuse_conn *fc = get_fuse_conn(inode);
	struct fuse_inode *fi = get_fuse_inode(inode);
	bool refreshed = false;
	int err = 0;

@@ -778,12 +791,11 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
		return -EACCES;

	/*
	 * If attributes are needed, but are stale, refresh them
	 * before proceeding
	 * If attributes are needed, refresh them before proceeding
	 */
	if (((fc->flags & FUSE_DEFAULT_PERMISSIONS) || (mask & MAY_EXEC)) &&
	    fi->i_time < get_jiffies_64()) {
		err = fuse_do_getattr(inode);
	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
		err = fuse_refresh_attributes(inode);
		if (err)
			return err;

@@ -806,14 +818,17 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
		   exist.  So if permissions are revoked this won't be
		   noticed immediately, only after the attribute
		   timeout has expired */

	} else {
		int mode = inode->i_mode;
		if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
	} else if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) {
		err = fuse_access(inode, mask);
	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
		if (!(inode->i_mode & S_IXUGO)) {
			if (refreshed)
				return -EACCES;

		if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR)))
			return fuse_access(inode, mask);
			err = fuse_do_getattr(inode);
			if (!err && !(inode->i_mode & S_IXUGO))
				return -EACCES;
		}
	}
	return err;
}
@@ -1046,14 +1061,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
	struct inode *inode = entry->d_inode;
	struct fuse_inode *fi = get_fuse_inode(inode);
	struct fuse_conn *fc = get_fuse_conn(inode);
	int err = 0;
	int err;

	if (!fuse_allow_task(fc, current))
		return -EACCES;

	if (fi->i_time < get_jiffies_64())
		err = fuse_do_getattr(inode);

	err = fuse_refresh_attributes(inode);
	if (!err) {
		generic_fillattr(inode, stat);
		stat->mode = fi->orig_i_mode;