* [PATCH -V2 2/6] fs/9p: Add xattr callbacks for POSIX ACL
2010-08-26 11:19 [PATCH -V2 1/6] fs/9p: Implement POSIX ACL permission checking function Aneesh Kumar K.V
@ 2010-08-26 11:19 ` Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 3/6] fs/9p: Implement setting posix acl Aneesh Kumar K.V
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Aneesh Kumar K.V @ 2010-08-26 11:19 UTC (permalink / raw)
To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V
This patch implement fetching POSIX ACL from the server
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/9p/acl.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/9p/xattr.c | 4 +++
fs/9p/xattr.h | 2 +
3 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 5de599b..e122e63 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -93,3 +93,66 @@ int v9fs_check_acl(struct inode *inode, int mask)
}
return -EAGAIN;
}
+
+static size_t v9fs_xattr_list_acl_access(struct dentry *dentry, char *list,
+ size_t list_len, const char *name,
+ size_t name_len, int type)
+{
+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
+ if (list && size <= list_len)
+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
+ return size;
+}
+
+static size_t v9fs_xattr_list_acl_default(struct dentry *dentry, char *list,
+ size_t list_len, const char *name,
+ size_t name_len, int type)
+{
+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
+ if (list && size <= list_len)
+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
+ return size;
+}
+
+static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
+ void *buffer, size_t size, int type)
+{
+ struct posix_acl *acl;
+ int error;
+
+ if (strcmp(name, "") != 0)
+ return -EINVAL;
+
+ acl = v9fs_get_cached_acl(dentry->d_inode, type);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ if (acl == NULL)
+ return -ENODATA;
+ error = posix_acl_to_xattr(acl, buffer, size);
+ posix_acl_release(acl);
+
+ return error;
+}
+
+static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
+ const void *value, size_t size,
+ int flags, int type)
+{
+ return 0;
+}
+
+const struct xattr_handler v9fs_xattr_acl_access_handler = {
+ .prefix = POSIX_ACL_XATTR_ACCESS,
+ .flags = ACL_TYPE_ACCESS,
+ .list = v9fs_xattr_list_acl_access,
+ .get = v9fs_xattr_get_acl,
+ .set = v9fs_xattr_set_acl,
+};
+
+const struct xattr_handler v9fs_xattr_acl_default_handler = {
+ .prefix = POSIX_ACL_XATTR_DEFAULT,
+ .flags = ACL_TYPE_DEFAULT,
+ .list = v9fs_xattr_list_acl_default,
+ .get = v9fs_xattr_get_acl,
+ .set = v9fs_xattr_set_acl,
+};
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index a3696c9..a9ff0ca 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -164,5 +164,9 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
const struct xattr_handler *v9fs_xattr_handlers[] = {
&v9fs_xattr_user_handler,
+#ifdef CONFIG_9P_FS_POSIX_ACL
+ &v9fs_xattr_acl_access_handler,
+ &v9fs_xattr_acl_default_handler,
+#endif
NULL
};
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h
index ec908c6..eaa837c 100644
--- a/fs/9p/xattr.h
+++ b/fs/9p/xattr.h
@@ -20,6 +20,8 @@
extern const struct xattr_handler *v9fs_xattr_handlers[];
extern struct xattr_handler v9fs_xattr_user_handler;
+extern const struct xattr_handler v9fs_xattr_acl_access_handler;
+extern const struct xattr_handler v9fs_xattr_acl_default_handler;
extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *,
void *, size_t);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH -V2 3/6] fs/9p: Implement setting posix acl
2010-08-26 11:19 [PATCH -V2 1/6] fs/9p: Implement POSIX ACL permission checking function Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 2/6] fs/9p: Add xattr callbacks for POSIX ACL Aneesh Kumar K.V
@ 2010-08-26 11:19 ` Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 4/6] fs/9p: Update ACL on chmod Aneesh Kumar K.V
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Aneesh Kumar K.V @ 2010-08-26 11:19 UTC (permalink / raw)
To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V
This patch also update mode bits, as a normal file system.
I am not sure wether we should do that, considering that
a setxattr on the server will again update the ACL/mode value
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/9p/acl.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
fs/9p/v9fs_vfs.h | 1 +
fs/9p/vfs_inode.c | 2 +-
3 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index e122e63..fc06467 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -17,8 +17,11 @@
#include <net/9p/9p.h>
#include <net/9p/client.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include <linux/posix_acl_xattr.h>
#include "xattr.h"
+#include "v9fs_vfs.h"
+
static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
{
@@ -138,7 +141,77 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
const void *value, size_t size,
int flags, int type)
{
- return 0;
+ int retval;
+ struct posix_acl *acl;
+ struct inode *inode = dentry->d_inode;
+
+ if (strcmp(name, "") != 0)
+ return -EINVAL;
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+ if (value) {
+ /* update the cached acl value */
+ acl = posix_acl_from_xattr(value, size);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ else if (acl) {
+ retval = posix_acl_valid(acl);
+ if (retval)
+ goto err_out;
+ }
+ } else
+ acl = NULL;
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = POSIX_ACL_XATTR_ACCESS;
+ if (acl) {
+ mode_t mode = inode->i_mode;
+ retval = posix_acl_equiv_mode(acl, &mode);
+ if (retval < 0)
+ goto err_out;
+ else {
+ struct iattr iattr;
+ if (retval == 0) {
+ /*
+ * ACL can be represented
+ * by the mode bits. So don't
+ * update ACL.
+ */
+ acl = NULL;
+ value = NULL;
+ size = 0;
+ }
+ /* Updte the mode bits */
+ iattr.ia_mode = ((mode & S_IALLUGO) |
+ (inode->i_mode & ~S_IALLUGO));
+ iattr.ia_valid = ATTR_MODE;
+ /* FIXME should we update ctime ?
+ * What is the following setxattr update the
+ * mode ?
+ */
+ v9fs_vfs_setattr_dotl(dentry, &iattr);
+ }
+ }
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = POSIX_ACL_XATTR_DEFAULT;
+ if (!S_ISDIR(inode->i_mode)) {
+ retval = -EINVAL;
+ goto err_out;
+ }
+ break;
+ default:
+ BUG();
+ }
+ retval = v9fs_xattr_set(dentry, name, value, size, flags);
+ if (!retval)
+ set_cached_acl(inode, type, acl);
+err_out:
+ posix_acl_release(acl);
+ return retval;
}
const struct xattr_handler v9fs_xattr_acl_access_handler = {
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index f47c6bb..6e87de5 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -64,3 +64,4 @@ int v9fs_uflags2omode(int uflags, int extended);
ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
void v9fs_blank_wstat(struct p9_wstat *wstat);
+int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7f0aac1..8f5bf6b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1248,7 +1248,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
*
*/
-static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
+int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
{
int retval;
struct v9fs_session_info *v9ses;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH -V2 4/6] fs/9p: Update ACL on chmod
2010-08-26 11:19 [PATCH -V2 1/6] fs/9p: Implement POSIX ACL permission checking function Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 2/6] fs/9p: Add xattr callbacks for POSIX ACL Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 3/6] fs/9p: Implement setting posix acl Aneesh Kumar K.V
@ 2010-08-26 11:19 ` Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 5/6] fs/9p: Implement create time inheritance Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 6/6] fs/9p: Add access = client option to opt in acl evaluation Aneesh Kumar K.V
4 siblings, 0 replies; 6+ messages in thread
From: Aneesh Kumar K.V @ 2010-08-26 11:19 UTC (permalink / raw)
To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V
We need update the acl value on chmod
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/9p/acl.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/9p/acl.h | 5 ++++
fs/9p/vfs_inode.c | 4 +++
3 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index fc06467..d717487 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -97,6 +97,61 @@ int v9fs_check_acl(struct inode *inode, int mask)
return -EAGAIN;
}
+static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
+{
+ int retval;
+ char *name;
+ size_t size;
+ void *buffer;
+ struct inode *inode = dentry->d_inode;
+
+ set_cached_acl(inode, type, acl);
+ /* Set a setxattr request to server */
+ size = posix_acl_xattr_size(acl->a_count);
+ buffer = kmalloc(size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ retval = posix_acl_to_xattr(acl, buffer, size);
+ if (retval)
+ goto err_free_out;
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = POSIX_ACL_XATTR_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = POSIX_ACL_XATTR_DEFAULT;
+ break;
+ default:
+ BUG();
+ }
+ retval = v9fs_xattr_set(dentry, name, buffer, size, 0);
+err_free_out:
+ kfree(buffer);
+ return retval;
+}
+
+int v9fs_acl_chmod(struct dentry *dentry)
+{
+ int retval = 0;
+ struct posix_acl *acl, *clone;
+ struct inode *inode = dentry->d_inode;
+
+ if (S_ISLNK(inode->i_mode))
+ return -EOPNOTSUPP;
+ acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
+ if (acl) {
+ clone = posix_acl_clone(acl, GFP_KERNEL);
+ posix_acl_release(acl);
+ if (!clone)
+ return -ENOMEM;
+ retval = posix_acl_chmod_masq(clone, inode->i_mode);
+ if (!retval)
+ retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, clone);
+ posix_acl_release(clone);
+ }
+ return retval;
+}
+
static size_t v9fs_xattr_list_acl_access(struct dentry *dentry, char *list,
size_t list_len, const char *name,
size_t name_len, int type)
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index 4c63eb1..2409e17 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -17,11 +17,16 @@
#ifdef CONFIG_9P_FS_POSIX_ACL
extern int v9fs_get_acl(struct inode *, struct p9_fid *);
extern int v9fs_check_acl(struct inode *inode, int mask);
+extern int v9fs_acl_chmod(struct dentry *);
#else
#define v9fs_check_acl NULL
static inline int v9fs_get_acl(struct inode *, struct p9_fid *)
{
return 0;
}
+static inline int v9fs_acl_chmod(struct dentry *dentry)
+{
+ return 0;
+}
#endif
#endif /* FS_9P_XATTR_H */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 8f5bf6b..6fb80e5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1238,6 +1238,10 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (retval >= 0)
retval = inode_setattr(dentry->d_inode, iattr);
+ if (!retval && (iattr->ia_valid & ATTR_MODE))
+ /* We also want to update ACL when we update mode bits */
+ retval = v9fs_acl_chmod(dentry);
+
return retval;
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH -V2 5/6] fs/9p: Implement create time inheritance
2010-08-26 11:19 [PATCH -V2 1/6] fs/9p: Implement POSIX ACL permission checking function Aneesh Kumar K.V
` (2 preceding siblings ...)
2010-08-26 11:19 ` [PATCH -V2 4/6] fs/9p: Update ACL on chmod Aneesh Kumar K.V
@ 2010-08-26 11:19 ` Aneesh Kumar K.V
2010-08-26 11:19 ` [PATCH -V2 6/6] fs/9p: Add access = client option to opt in acl evaluation Aneesh Kumar K.V
4 siblings, 0 replies; 6+ messages in thread
From: Aneesh Kumar K.V @ 2010-08-26 11:19 UTC (permalink / raw)
To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V
Inherit default ACL on create
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
fs/9p/acl.c | 52 +++++++++++++++++++++++++++++++++++++++++
fs/9p/acl.h | 16 ++++++++++++
fs/9p/vfs_inode.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 126 insertions(+), 9 deletions(-)
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index d717487..e7982a1 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -152,6 +152,58 @@ int v9fs_acl_chmod(struct dentry *dentry)
return retval;
}
+int v9fs_set_create_acl(struct dentry *dentry,
+ struct posix_acl *dpacl, struct posix_acl *pacl)
+{
+ if (dpacl)
+ v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
+ if (pacl)
+ v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
+ posix_acl_release(dpacl);
+ posix_acl_release(pacl);
+ return 0;
+}
+
+int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+ struct posix_acl **dpacl, struct posix_acl **pacl)
+{
+ int retval = 0;
+ mode_t mode = *modep;
+ struct posix_acl *acl = NULL;
+
+ if (!S_ISLNK(mode)) {
+ acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ if (!acl)
+ mode &= ~current_umask();
+ }
+ if (acl) {
+ struct posix_acl *clone;
+
+ if (S_ISDIR(mode))
+ *dpacl = acl;
+ clone = posix_acl_clone(acl, GFP_NOFS);
+ retval = -ENOMEM;
+ if (!clone)
+ goto cleanup;
+
+ retval = posix_acl_create_masq(clone, &mode);
+ if (retval < 0) {
+ posix_acl_release(clone);
+ goto cleanup;
+ }
+ if (retval > 0)
+ *pacl = clone;
+ }
+ *modep = mode;
+ return 0;
+cleanup:
+ posix_acl_release(acl);
+ return retval;
+
+}
+
static size_t v9fs_xattr_list_acl_access(struct dentry *dentry, char *list,
size_t list_len, const char *name,
size_t name_len, int type)
diff --git a/fs/9p/acl.h b/fs/9p/acl.h
index 2409e17..3b9d99f 100644
--- a/fs/9p/acl.h
+++ b/fs/9p/acl.h
@@ -18,6 +18,10 @@
extern int v9fs_get_acl(struct inode *, struct p9_fid *);
extern int v9fs_check_acl(struct inode *inode, int mask);
extern int v9fs_acl_chmod(struct dentry *);
+extern int v9fs_set_create_acl(struct dentry *,
+ struct posix_acl *, struct posix_acl *);
+extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+ struct posix_acl **dpacl, struct posix_acl **pacl);
#else
#define v9fs_check_acl NULL
static inline int v9fs_get_acl(struct inode *, struct p9_fid *)
@@ -28,5 +32,17 @@ static inline int v9fs_acl_chmod(struct dentry *dentry)
{
return 0;
}
+static inline int v9fs_set_create_acl(struct dentry *,
+ struct posix_acl *, struct posix_acl *)
+{
+ return 0;
+}
+static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep,
+ struct posix_acl **dpacl,
+ struct posix_acl **pacl)
+{
+ return 0;
+}
+
#endif
#endif /* FS_9P_XATTR_H */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 6fb80e5..3e365f6 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -636,6 +636,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
goto error;
}
}
+
/* instantiate inode and assign the unopened fid to the dentry */
inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
if (IS_ERR(inode)) {
@@ -676,19 +677,21 @@ error:
*/
static int
-v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
+v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
struct nameidata *nd)
{
int err = 0;
char *name = NULL;
gid_t gid;
int flags;
+ mode_t mode;
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL;
struct p9_fid *dfid, *ofid;
struct file *filp;
struct p9_qid qid;
struct inode *inode;
+ struct posix_acl *pacl = NULL, *dacl = NULL;
v9ses = v9fs_inode2v9ses(dir);
if (nd && nd->flags & LOOKUP_OPEN)
@@ -698,7 +701,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
name = (char *) dentry->d_name.name;
P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x "
- "mode:0x%x\n", name, flags, mode);
+ "mode:0x%x\n", name, flags, omode);
dfid = v9fs_fid_lookup(dentry->d_parent);
if (IS_ERR(dfid)) {
@@ -716,6 +719,15 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
}
gid = v9fs_get_fsgid_for_create(dir);
+
+ mode = omode;
+ /* Update mode based on ACL value */
+ err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
+ if (err) {
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "Failed to get acl values in creat %d\n", err);
+ goto error;
+ }
err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
if (err < 0) {
P9_DPRINTK(P9_DEBUG_VFS,
@@ -760,6 +772,9 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
if (err < 0)
goto error;
+ /* Now set the ACL based on the default value */
+ v9fs_set_create_acl(dentry, dacl, pacl);
+
/* if we are opening a file, assign the open fid to the file */
if (nd && nd->flags & LOOKUP_OPEN) {
filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
@@ -880,23 +895,25 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
*
*/
-static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
- int mode)
+static int v9fs_vfs_mkdir_dotl(struct inode *dir,
+ struct dentry *dentry, int omode)
{
int err;
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL;
gid_t gid;
char *name;
+ mode_t mode;
struct inode *inode;
struct p9_qid qid;
struct dentry *dir_dentry;
+ struct posix_acl *dacl = NULL, *pacl = NULL;
P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
err = 0;
v9ses = v9fs_inode2v9ses(dir);
- mode |= S_IFDIR;
+ omode |= S_IFDIR;
dir_dentry = v9fs_dentry_from_dir_inode(dir);
dfid = v9fs_fid_lookup(dir_dentry);
if (IS_ERR(dfid)) {
@@ -911,7 +928,14 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n");
goto error;
}
-
+ mode = omode;
+ /* Update mode based on ACL value */
+ err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
+ if (err) {
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "Failed to get acl values in mkdir %d\n", err);
+ goto error;
+ }
name = (char *) dentry->d_name.name;
err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
if (err < 0)
@@ -941,7 +965,23 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
if (err < 0)
goto error;
fid = NULL;
+ } else {
+ /*
+ * Not in cached mode. No need to populate
+ * inode with stat. We need to get an inode
+ * so that we can set the acl with dentry
+ */
+ inode = v9fs_get_inode(dir->i_sb, mode);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ goto error;
+ }
+ dentry->d_op = &v9fs_dentry_operations;
+ d_instantiate(dentry, inode);
}
+ /* Now set the ACL based on the default value */
+ v9fs_set_create_acl(dentry, dacl, pacl);
+
error:
if (fid)
p9_client_clunk(fid);
@@ -1859,21 +1899,23 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
*
*/
static int
-v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
+v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
dev_t rdev)
{
int err;
char *name;
+ mode_t mode;
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL;
struct inode *inode;
gid_t gid;
struct p9_qid qid;
struct dentry *dir_dentry;
+ struct posix_acl *dacl = NULL, *pacl = NULL;
P9_DPRINTK(P9_DEBUG_VFS,
" %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
- dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
+ dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev));
if (!new_valid_dev(rdev))
return -EINVAL;
@@ -1893,7 +1935,14 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n");
goto error;
}
-
+ mode = omode;
+ /* Update mode based on ACL value */
+ err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
+ if (err) {
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "Failed to get acl values in mknod %d\n", err);
+ goto error;
+ }
name = (char *) dentry->d_name.name;
err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH -V2 6/6] fs/9p: Add access = client option to opt in acl evaluation.
2010-08-26 11:19 [PATCH -V2 1/6] fs/9p: Implement POSIX ACL permission checking function Aneesh Kumar K.V
` (3 preceding siblings ...)
2010-08-26 11:19 ` [PATCH -V2 5/6] fs/9p: Implement create time inheritance Aneesh Kumar K.V
@ 2010-08-26 11:19 ` Aneesh Kumar K.V
4 siblings, 0 replies; 6+ messages in thread
From: Aneesh Kumar K.V @ 2010-08-26 11:19 UTC (permalink / raw)
To: v9fs-developer; +Cc: linux-fsdevel, linux-kernel, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
Documentation/filesystems/9p.txt | 4 +++-
fs/9p/acl.c | 37 ++++++++++++++++++++++++++++++++++++-
fs/9p/fid.c | 1 +
fs/9p/v9fs.c | 12 ++++++++++++
fs/9p/v9fs.h | 8 ++++++--
fs/9p/vfs_inode.c | 14 ++++++++++----
fs/9p/vfs_super.c | 16 +++++++++++-----
7 files changed, 79 insertions(+), 13 deletions(-)
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt
index c0236e7..1a48155 100644
--- a/Documentation/filesystems/9p.txt
+++ b/Documentation/filesystems/9p.txt
@@ -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
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index e7982a1..96fa9fc 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -21,6 +21,7 @@
#include <linux/posix_acl_xattr.h>
#include "xattr.h"
#include "v9fs_vfs.h"
+#include "v9fs.h"
static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
@@ -85,7 +86,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);
@@ -208,7 +220,13 @@ static size_t v9fs_xattr_list_acl_access(struct dentry *dentry, char *list,
size_t list_len, const char *name,
size_t name_len, int type)
{
+ struct v9fs_session_info *v9ses;
const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
+ return 0;
+
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
return size;
@@ -218,7 +236,13 @@ static size_t v9fs_xattr_list_acl_default(struct dentry *dentry, char *list,
size_t list_len, const char *name,
size_t name_len, int type)
{
+ struct v9fs_session_info *v9ses;
const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
+ return 0;
+
if (list && size <= list_len)
memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
return size;
@@ -227,12 +251,17 @@ static size_t v9fs_xattr_list_acl_default(struct dentry *dentry, char *list,
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);
+ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
+ return -EOPNOTSUPP;
+
acl = v9fs_get_cached_acl(dentry->d_inode, type);
if (IS_ERR(acl))
return PTR_ERR(acl);
@@ -250,10 +279,16 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
{
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);
+ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
+ return -EOPNOTSUPP;
+
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (!is_owner_or_cap(inode))
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 3585636..4876a0e 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -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;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 38dc0e0..735ff25 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -193,6 +193,8 @@ 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 if (strcmp(s, "client") == 0)
+ v9ses->flags |= V9FS_ACCESS_CLIENT;
else {
v9ses->flags |= V9FS_ACCESS_SINGLE;
v9ses->uid = simple_strtoul(s, &e, 10);
@@ -278,6 +280,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)) {
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 4c963c9..8bb7792 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -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 */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 3e365f6..9040db5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -500,10 +500,16 @@ v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
v9fs_vcookie_set_qid(ret, &st->qid);
v9fs_cache_inode_get_cookie(ret);
#endif
- err = v9fs_get_acl(ret, fid);
- if (err) {
- iput(ret);
- goto error;
+ if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT) {
+ /*
+ * On access = client mode get the acl
+ * values from the server
+ */
+ err = v9fs_get_acl(ret, fid);
+ if (err) {
+ iput(ret);
+ goto error;
+ }
}
kfree(st);
return ret;
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index a120a48..e15e9ac 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -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);
@@ -178,10 +179,15 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
p9stat_free(st);
kfree(st);
}
- retval = v9fs_get_acl(inode, fid);
- if (retval)
- goto release_sb;
-
+ if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT) {
+ /*
+ * On access = client mode get the acl
+ * values from the server
+ */
+ 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");
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread