From e8e961574b5b417d3fc277cbf436081fce4fc2e1 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 16 Oct 2007 23:31:06 -0700 Subject: [PATCH] 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: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8ea4ea13ec5f..d1acab931330 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -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 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; - } else { - int mode = inode->i_mode; - if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) - 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;