fs/9p: Add access = client option to opt in acl evaluation.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
This commit is contained in:
Aneesh Kumar K.V 2010-09-28 00:27:41 +05:30 committed by Eric Van Hensbergen
parent ad77dbce56
commit 76381a42e4
6 changed files with 110 additions and 7 deletions

View file

@ -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.
@ -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

View file

@ -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)
{
@ -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);
@ -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);
@ -204,15 +223,41 @@ cleanup:
}
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);
@ -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))

View file

@ -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;

View file

@ -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')
@ -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)) {

View file

@ -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 */

View file

@ -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);
@ -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");