Message ID | 1467294433-3222-20-git-send-email-agruenba@redhat.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
On Thu, 2016-06-30 at 15:47 +0200, Andreas Gruenbacher wrote: > Add richacl xattr handler implementing the xattr operations based on the > get_richacl and set_richacl inode operations. > > Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> > --- > fs/richacl.c | 22 ++++++++++++++++ > fs/richacl_xattr.c | 61 +++++++++++++++++++++++++++++++++++++++++++ > include/linux/richacl.h | 1 + > include/linux/richacl_xattr.h | 2 ++ > 4 files changed, 86 insertions(+) > > diff --git a/fs/richacl.c b/fs/richacl.c > index 40e4af9..b7d7104 100644 > --- a/fs/richacl.c > +++ b/fs/richacl.c > @@ -549,6 +549,28 @@ out: > EXPORT_SYMBOL_GPL(richacl_permission); > > /** > + * set_richacl - set the richacl of an inode > + * @inode: inode whose richacl to set > + * @acl: access control list > + */ > +int > +set_richacl(struct inode *inode, struct richacl *acl) > +{ > + if (!IS_RICHACL(inode)) > + return -EOPNOTSUPP; > + if (!inode->i_op->set_richacl) > + return -EOPNOTSUPP; > + > + if (!uid_eq(current_fsuid(), inode->i_uid) && > + inode_permission(inode, MAY_CHMOD) && > + !capable(CAP_FOWNER)) > + return -EPERM; > + > + return inode->i_op->set_richacl(inode, acl); > +} > +EXPORT_SYMBOL(set_richacl); > + > +/** > * __richacl_chmod - update the file masks to reflect the new mode > * @acl: access control list > * @mode: new file permission bits including the file type > diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c > index dc1ad36..5eb4aba 100644 > --- a/fs/richacl_xattr.c > +++ b/fs/richacl_xattr.c > @@ -18,7 +18,9 @@ > #include > #include > #include > +#include > #include > +#include > > /** > * richacl_from_xattr - convert a richacl xattr into the in-memory representation > @@ -159,3 +161,62 @@ richacl_to_xattr(struct user_namespace *user_ns, > return real_size; > } > EXPORT_SYMBOL_GPL(richacl_to_xattr); > + > +static bool > +richacl_xattr_list(struct dentry *dentry) > +{ > + return IS_RICHACL(d_backing_inode(dentry)); > +} > + > +static int > +richacl_xattr_get(const struct xattr_handler *handler, > + struct dentry *unused, struct inode *inode, > + const char *name, void *buffer, size_t buffer_size) > +{ > + struct richacl *acl; > + int error; > + > + if (*name) > + return -EINVAL; > + if (!IS_RICHACL(inode)) > + return -EOPNOTSUPP; > + if (S_ISLNK(inode->i_mode)) > + return -EOPNOTSUPP; > + acl = get_richacl(inode); > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + if (acl == NULL) > + return -ENODATA; > + error = richacl_to_xattr(current_user_ns(), acl, buffer, buffer_size); > + richacl_put(acl); > + return error; > +} > + > +static int > +richacl_xattr_set(const struct xattr_handler *handler, > + struct dentry *unused, struct inode *inode, > + const char *name, const void *value, size_t size, > + int flags) > +{ > + struct richacl *acl = NULL; > + int ret; > + > + if (value) { > + acl = richacl_from_xattr(current_user_ns(), value, size, > + -EINVAL); > + if (IS_ERR(acl)) > + return PTR_ERR(acl); > + } > + > + ret = set_richacl(inode, acl); > + richacl_put(acl); > + return ret; > +} > + > +struct xattr_handler richacl_xattr_handler = { > + .name = XATTR_NAME_RICHACL, > + .list = richacl_xattr_list, > + .get = richacl_xattr_get, > + .set = richacl_xattr_set, > +}; > +EXPORT_SYMBOL(richacl_xattr_handler); > diff --git a/include/linux/richacl.h b/include/linux/richacl.h > index a442372..e7db066 100644 > --- a/include/linux/richacl.h > +++ b/include/linux/richacl.h > @@ -206,5 +206,6 @@ extern int richacl_chmod(struct inode *, umode_t); > extern int richacl_equiv_mode(const struct richacl *, umode_t *); > extern struct richacl *richacl_inherit(const struct richacl *, int); > extern struct richacl *richacl_create(umode_t *, struct inode *); > +extern int set_richacl(struct inode *, struct richacl *); > > #endif /* __RICHACL_H */ > diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h > index 0efa14b..6c6adb1 100644 > --- a/include/linux/richacl_xattr.h > +++ b/include/linux/richacl_xattr.h > @@ -26,4 +26,6 @@ extern size_t richacl_xattr_size(const struct richacl *); > extern int richacl_to_xattr(struct user_namespace *, const struct richacl *, > void *, size_t); > > +extern struct xattr_handler richacl_xattr_handler; > + > #endif /* __RICHACL_XATTR_H */ Cue same refrain about syscalls vs. xattrs. Otherwise: Reviewed-by: Jeff Layton <jlayton@redhat.com>
diff --git a/fs/richacl.c b/fs/richacl.c index 40e4af9..b7d7104 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -549,6 +549,28 @@ out: EXPORT_SYMBOL_GPL(richacl_permission); /** + * set_richacl - set the richacl of an inode + * @inode: inode whose richacl to set + * @acl: access control list + */ +int +set_richacl(struct inode *inode, struct richacl *acl) +{ + if (!IS_RICHACL(inode)) + return -EOPNOTSUPP; + if (!inode->i_op->set_richacl) + return -EOPNOTSUPP; + + if (!uid_eq(current_fsuid(), inode->i_uid) && + inode_permission(inode, MAY_CHMOD) && + !capable(CAP_FOWNER)) + return -EPERM; + + return inode->i_op->set_richacl(inode, acl); +} +EXPORT_SYMBOL(set_richacl); + +/** * __richacl_chmod - update the file masks to reflect the new mode * @acl: access control list * @mode: new file permission bits including the file type diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c index dc1ad36..5eb4aba 100644 --- a/fs/richacl_xattr.c +++ b/fs/richacl_xattr.c @@ -18,7 +18,9 @@ #include <linux/fs.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/xattr.h> #include <linux/richacl_xattr.h> +#include <uapi/linux/xattr.h> /** * richacl_from_xattr - convert a richacl xattr into the in-memory representation @@ -159,3 +161,62 @@ richacl_to_xattr(struct user_namespace *user_ns, return real_size; } EXPORT_SYMBOL_GPL(richacl_to_xattr); + +static bool +richacl_xattr_list(struct dentry *dentry) +{ + return IS_RICHACL(d_backing_inode(dentry)); +} + +static int +richacl_xattr_get(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t buffer_size) +{ + struct richacl *acl; + int error; + + if (*name) + return -EINVAL; + if (!IS_RICHACL(inode)) + return -EOPNOTSUPP; + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + acl = get_richacl(inode); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl == NULL) + return -ENODATA; + error = richacl_to_xattr(current_user_ns(), acl, buffer, buffer_size); + richacl_put(acl); + return error; +} + +static int +richacl_xattr_set(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) +{ + struct richacl *acl = NULL; + int ret; + + if (value) { + acl = richacl_from_xattr(current_user_ns(), value, size, + -EINVAL); + if (IS_ERR(acl)) + return PTR_ERR(acl); + } + + ret = set_richacl(inode, acl); + richacl_put(acl); + return ret; +} + +struct xattr_handler richacl_xattr_handler = { + .name = XATTR_NAME_RICHACL, + .list = richacl_xattr_list, + .get = richacl_xattr_get, + .set = richacl_xattr_set, +}; +EXPORT_SYMBOL(richacl_xattr_handler); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index a442372..e7db066 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -206,5 +206,6 @@ extern int richacl_chmod(struct inode *, umode_t); extern int richacl_equiv_mode(const struct richacl *, umode_t *); extern struct richacl *richacl_inherit(const struct richacl *, int); extern struct richacl *richacl_create(umode_t *, struct inode *); +extern int set_richacl(struct inode *, struct richacl *); #endif /* __RICHACL_H */ diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h index 0efa14b..6c6adb1 100644 --- a/include/linux/richacl_xattr.h +++ b/include/linux/richacl_xattr.h @@ -26,4 +26,6 @@ extern size_t richacl_xattr_size(const struct richacl *); extern int richacl_to_xattr(struct user_namespace *, const struct richacl *, void *, size_t); +extern struct xattr_handler richacl_xattr_handler; + #endif /* __RICHACL_XATTR_H */
Add richacl xattr handler implementing the xattr operations based on the get_richacl and set_richacl inode operations. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/richacl.c | 22 ++++++++++++++++ fs/richacl_xattr.c | 61 +++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + include/linux/richacl_xattr.h | 2 ++ 4 files changed, 86 insertions(+)