Browse Source

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>
Aneesh Kumar K.V 14 years ago
parent
commit
76381a42e4
6 changed files with 110 additions and 7 deletions
  1. 3 1
      Documentation/filesystems/9p.txt
  2. 77 1
      fs/9p/acl.c
  3. 1 0
      fs/9p/fid.c
  4. 21 1
      fs/9p/v9fs.c
  5. 6 2
      fs/9p/v9fs.h
  6. 2 2
      fs/9p/vfs_super.c

+ 3 - 1
Documentation/filesystems/9p.txt

@@ -111,7 +111,7 @@ OPTIONS
   		This can be used to share devices/named pipes/sockets between
   		This can be used to share devices/named pipes/sockets between
 		hosts.  This functionality will be expanded in later versions.
 		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
 			user  = if a user tries to access a file on v9fs
 			        filesystem for the first time, v9fs sends an
 			        filesystem for the first time, v9fs sends an
 			        attach command (Tattach) for that user.
 			        attach command (Tattach) for that user.
@@ -120,6 +120,8 @@ OPTIONS
 				the files on the mounted filesystem
 				the files on the mounted filesystem
 			any   = v9fs does single attach and performs all
 			any   = v9fs does single attach and performs all
 				operations as one user
 				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.
   cachetag	cache tag to use the specified persistent cache.
 		cache tags for existing cache sessions can be listed at
 		cache tags for existing cache sessions can be listed at

+ 77 - 1
fs/9p/acl.c

@@ -22,6 +22,7 @@
 #include "xattr.h"
 #include "xattr.h"
 #include "acl.h"
 #include "acl.h"
 #include "v9fs_vfs.h"
 #include "v9fs_vfs.h"
+#include "v9fs.h"
 
 
 static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
 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;
 	int retval = 0;
 	struct posix_acl *pacl, *dacl;
 	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 */
 	/* get the default/access acl values and cache them */
 	dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
 	dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
 	pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
 	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)
 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))
 	if (IS_ERR(acl))
 		return PTR_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,
 static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 			      void *buffer, size_t size, int type)
 			      void *buffer, size_t size, int type)
 {
 {
+	struct v9fs_session_info *v9ses;
 	struct posix_acl *acl;
 	struct posix_acl *acl;
 	int error;
 	int error;
 
 
 	if (strcmp(name, "") != 0)
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 		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);
 	acl = v9fs_get_cached_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 		return PTR_ERR(acl);
@@ -224,16 +269,47 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	return error;
 	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,
 static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 			      const void *value, size_t size,
 			      const void *value, size_t size,
 			      int flags, int type)
 			      int flags, int type)
 {
 {
 	int retval;
 	int retval;
 	struct posix_acl *acl;
 	struct posix_acl *acl;
+	struct v9fs_session_info *v9ses;
 	struct inode *inode = dentry->d_inode;
 	struct inode *inode = dentry->d_inode;
 
 
 	if (strcmp(name, "") != 0)
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 		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))
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 	if (!is_owner_or_cap(inode))
 	if (!is_owner_or_cap(inode))

+ 1 - 0
fs/9p/fid.c

@@ -149,6 +149,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 	switch (access) {
 	switch (access) {
 	case V9FS_ACCESS_SINGLE:
 	case V9FS_ACCESS_SINGLE:
 	case V9FS_ACCESS_USER:
 	case V9FS_ACCESS_USER:
+	case V9FS_ACCESS_CLIENT:
 		uid = current_fsuid();
 		uid = current_fsuid();
 		any = 0;
 		any = 0;
 		break;
 		break;

+ 21 - 1
fs/9p/v9fs.c

@@ -193,7 +193,17 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 				v9ses->flags |= V9FS_ACCESS_USER;
 				v9ses->flags |= V9FS_ACCESS_USER;
 			else if (strcmp(s, "any") == 0)
 			else if (strcmp(s, "any") == 0)
 				v9ses->flags |= V9FS_ACCESS_ANY;
 				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->flags |= V9FS_ACCESS_SINGLE;
 				v9ses->uid = simple_strtoul(s, &e, 10);
 				v9ses->uid = simple_strtoul(s, &e, 10);
 				if (*e != '\0')
 				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;
 	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 */
 	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
 	if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
 	if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {

+ 6 - 2
fs/9p/v9fs.h

@@ -33,13 +33,17 @@
  *
  *
  * Session flags reflect options selected by users at mount time
  * 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 {
 enum p9_session_flags {
 	V9FS_PROTO_2000U	= 0x01,
 	V9FS_PROTO_2000U	= 0x01,
 	V9FS_PROTO_2000L	= 0x02,
 	V9FS_PROTO_2000L	= 0x02,
 	V9FS_ACCESS_SINGLE	= 0x04,
 	V9FS_ACCESS_SINGLE	= 0x04,
 	V9FS_ACCESS_USER	= 0x08,
 	V9FS_ACCESS_USER	= 0x08,
-	V9FS_ACCESS_ANY		= 0x0C,
-	V9FS_ACCESS_MASK	= 0x0C,
+	V9FS_ACCESS_CLIENT	= 0x10
 };
 };
 
 
 /* possible values of ->cache */
 /* possible values of ->cache */

+ 2 - 2
fs/9p/vfs_super.c

@@ -90,7 +90,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 	    MS_NOATIME;
 	    MS_NOATIME;
 
 
 #ifdef CONFIG_9P_FS_POSIX_ACL
 #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
 #endif
 
 
 	save_mount_options(sb, data);
 	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);
 	retval = v9fs_get_acl(inode, fid);
 	if (retval)
 	if (retval)
 		goto release_sb;
 		goto release_sb;
-
 	v9fs_fid_add(root, fid);
 	v9fs_fid_add(root, fid);
 
 
 	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
 	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");