[PATCH] FUSE: add access call
Add a new access call, which will only be called if ->permission is invoked from sys_access(). In all other cases permission checking is delayed until the actual filesystem operation. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
5b62073d50
commit
31d40d74b4
@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry)
|
|||||||
return fuse_do_getattr(inode);
|
return fuse_do_getattr(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fuse_access(struct inode *inode, int mask)
|
||||||
|
{
|
||||||
|
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||||
|
struct fuse_req *req;
|
||||||
|
struct fuse_access_in inarg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (fc->no_access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
req = fuse_get_request(fc);
|
||||||
|
if (!req)
|
||||||
|
return -EINTR;
|
||||||
|
|
||||||
|
memset(&inarg, 0, sizeof(inarg));
|
||||||
|
inarg.mask = mask;
|
||||||
|
req->in.h.opcode = FUSE_ACCESS;
|
||||||
|
req->in.h.nodeid = get_node_id(inode);
|
||||||
|
req->inode = inode;
|
||||||
|
req->in.numargs = 1;
|
||||||
|
req->in.args[0].size = sizeof(inarg);
|
||||||
|
req->in.args[0].value = &inarg;
|
||||||
|
request_send(fc, req);
|
||||||
|
err = req->out.h.error;
|
||||||
|
fuse_put_request(fc, req);
|
||||||
|
if (err == -ENOSYS) {
|
||||||
|
fc->no_access = 1;
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
|
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct fuse_conn *fc = get_fuse_conn(inode);
|
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||||
@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
|
|||||||
int mode = inode->i_mode;
|
int mode = inode->i_mode;
|
||||||
if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
|
if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
|
if (nd && (nd->flags & LOOKUP_ACCESS))
|
||||||
|
return fuse_access(inode, mask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,9 @@ struct fuse_conn {
|
|||||||
/** Is removexattr not implemented by fs? */
|
/** Is removexattr not implemented by fs? */
|
||||||
unsigned no_removexattr : 1;
|
unsigned no_removexattr : 1;
|
||||||
|
|
||||||
|
/** Is access not implemented by fs? */
|
||||||
|
unsigned no_access : 1;
|
||||||
|
|
||||||
/** Backing dev info */
|
/** Backing dev info */
|
||||||
struct backing_dev_info bdi;
|
struct backing_dev_info bdi;
|
||||||
};
|
};
|
||||||
|
@ -99,7 +99,8 @@ enum fuse_opcode {
|
|||||||
FUSE_OPENDIR = 27,
|
FUSE_OPENDIR = 27,
|
||||||
FUSE_READDIR = 28,
|
FUSE_READDIR = 28,
|
||||||
FUSE_RELEASEDIR = 29,
|
FUSE_RELEASEDIR = 29,
|
||||||
FUSE_FSYNCDIR = 30
|
FUSE_FSYNCDIR = 30,
|
||||||
|
FUSE_ACCESS = 34
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Conservative buffer size for the client */
|
/* Conservative buffer size for the client */
|
||||||
@ -222,6 +223,11 @@ struct fuse_getxattr_out {
|
|||||||
__u32 padding;
|
__u32 padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fuse_access_in {
|
||||||
|
__u32 mask;
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
struct fuse_init_in_out {
|
struct fuse_init_in_out {
|
||||||
__u32 major;
|
__u32 major;
|
||||||
__u32 minor;
|
__u32 minor;
|
||||||
|
Loading…
Reference in New Issue
Block a user