Skip to content

Commit

Permalink
fs/9p: Add access = client option to opt in acl evaluation.
Browse files Browse the repository at this point in the history
Signed-off-by: Aneesh Kumar K.V <[email protected]>
Signed-off-by: Venkateswararao Jujjuri <[email protected]>
Signed-off-by: Eric Van Hensbergen <[email protected]>
  • Loading branch information
kvaneesh authored and ericvh committed Oct 28, 2010
1 parent ad77dbc commit 76381a4
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 7 deletions.
4 changes: 3 additions & 1 deletion Documentation/filesystems/9p.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ OPTIONS
This can be used to share devices/named pipes/sockets between
hosts. This functionality will be expanded in later versions.

access there are three access modes.
access there are four access modes.
user = if a user tries to access a file on v9fs
filesystem for the first time, v9fs sends an
attach command (Tattach) for that user.
Expand All @@ -120,6 +120,8 @@ OPTIONS
the files on the mounted filesystem
any = v9fs does single attach and performs all
operations as one user
client = ACL based access check on the 9p client
side for access validation

cachetag cache tag to use the specified persistent cache.
cache tags for existing cache sessions can be listed at
Expand Down
78 changes: 77 additions & 1 deletion fs/9p/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "xattr.h"
#include "acl.h"
#include "v9fs_vfs.h"
#include "v9fs.h"

static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
{
Expand Down Expand Up @@ -55,7 +56,14 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
{
int retval = 0;
struct posix_acl *pacl, *dacl;
struct v9fs_session_info *v9ses;

v9ses = v9fs_inode2v9ses(inode);
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL);
set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
return 0;
}
/* get the default/access acl values and cache them */
dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
Expand Down Expand Up @@ -85,7 +93,18 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)

int v9fs_check_acl(struct inode *inode, int mask)
{
struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
struct posix_acl *acl;
struct v9fs_session_info *v9ses;

v9ses = v9fs_inode2v9ses(inode);
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
/*
* On access = client mode get the acl
* values from the server
*/
return 0;
}
acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);

if (IS_ERR(acl))
return PTR_ERR(acl);
Expand Down Expand Up @@ -204,15 +223,41 @@ int v9fs_acl_mode(struct inode *dir, mode_t *modep,

}

static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
char *full_name;

switch (type) {
case ACL_TYPE_ACCESS:
full_name = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
full_name = POSIX_ACL_XATTR_DEFAULT;
break;
default:
BUG();
}
return v9fs_xattr_get(dentry, full_name, buffer, size);
}

static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type)
{
struct v9fs_session_info *v9ses;
struct posix_acl *acl;
int error;

if (strcmp(name, "") != 0)
return -EINVAL;

v9ses = v9fs_inode2v9ses(dentry->d_inode);
/*
* We allow set/get/list of acl when access=client is not specified
*/
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_remote_get_acl(dentry, name, buffer, size, type);

acl = v9fs_get_cached_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
Expand All @@ -224,16 +269,47 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
return error;
}

static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags, int type)
{
char *full_name;

switch (type) {
case ACL_TYPE_ACCESS:
full_name = POSIX_ACL_XATTR_ACCESS;
break;
case ACL_TYPE_DEFAULT:
full_name = POSIX_ACL_XATTR_DEFAULT;
break;
default:
BUG();
}
return v9fs_xattr_set(dentry, full_name, value, size, flags);
}


static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags, int type)
{
int retval;
struct posix_acl *acl;
struct v9fs_session_info *v9ses;
struct inode *inode = dentry->d_inode;

if (strcmp(name, "") != 0)
return -EINVAL;

v9ses = v9fs_inode2v9ses(dentry->d_inode);
/*
* set the attribute on the remote. Without even looking at the
* xattr value. We leave it to the server to validate
*/
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_remote_set_acl(dentry, name,
value, size, flags, type);

if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
Expand Down
1 change: 1 addition & 0 deletions fs/9p/fid.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
switch (access) {
case V9FS_ACCESS_SINGLE:
case V9FS_ACCESS_USER:
case V9FS_ACCESS_CLIENT:
uid = current_fsuid();
any = 0;
break;
Expand Down
22 changes: 21 additions & 1 deletion fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,17 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
v9ses->flags |= V9FS_ACCESS_USER;
else if (strcmp(s, "any") == 0)
v9ses->flags |= V9FS_ACCESS_ANY;
else {
else if (strcmp(s, "client") == 0) {
#ifdef CONFIG_9P_FS_POSIX_ACL
v9ses->flags |= V9FS_ACCESS_CLIENT;
#else
P9_DPRINTK(P9_DEBUG_ERROR,
"access=client option not supported\n");
kfree(s);
ret = -EINVAL;
goto free_and_return;
#endif
} else {
v9ses->flags |= V9FS_ACCESS_SINGLE;
v9ses->uid = simple_strtoul(s, &e, 10);
if (*e != '\0')
Expand Down Expand Up @@ -278,6 +288,16 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,

v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;

if (!v9fs_proto_dotl(v9ses) &&
((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
/*
* We support ACCESS_CLIENT only for dotl.
* Fall back to ACCESS_USER
*/
v9ses->flags &= ~V9FS_ACCESS_MASK;
v9ses->flags |= V9FS_ACCESS_USER;
}
/*FIXME !! */
/* for legacy mode, fall back to V9FS_ACCESS_ANY */
if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
Expand Down
8 changes: 6 additions & 2 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@
*
* Session flags reflect options selected by users at mount time
*/
#define V9FS_ACCESS_ANY (V9FS_ACCESS_SINGLE | \
V9FS_ACCESS_USER | \
V9FS_ACCESS_CLIENT)
#define V9FS_ACCESS_MASK V9FS_ACCESS_ANY

enum p9_session_flags {
V9FS_PROTO_2000U = 0x01,
V9FS_PROTO_2000L = 0x02,
V9FS_ACCESS_SINGLE = 0x04,
V9FS_ACCESS_USER = 0x08,
V9FS_ACCESS_ANY = 0x0C,
V9FS_ACCESS_MASK = 0x0C,
V9FS_ACCESS_CLIENT = 0x10
};

/* possible values of ->cache */
Expand Down
4 changes: 2 additions & 2 deletions fs/9p/vfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
MS_NOATIME;

#ifdef CONFIG_9P_FS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)
sb->s_flags |= MS_POSIXACL;
#endif

save_mount_options(sb, data);
Expand Down Expand Up @@ -181,7 +182,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
retval = v9fs_get_acl(inode, fid);
if (retval)
goto release_sb;

v9fs_fid_add(root, fid);

P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
Expand Down

0 comments on commit 76381a4

Please sign in to comment.