From: Seth Forshee <seth.forshee@canonical.com>
To: Michael j Theall <mtheall@us.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>,
fuse-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org,
Miklos Szeredi <miklos@szeredi.hu>
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLs
Date: Wed, 29 Jun 2016 15:56:06 -0500 [thread overview]
Message-ID: <20160629205606.GG53123@ubuntu-hedt> (raw)
In-Reply-To: <OFF8F0F486.DB2CEB73-ON86257FE1.006A1FF4-86257FE1.006A9703@notes.na.collabserv.com>
On Wed, Jun 29, 2016 at 02:24:14PM -0500, Michael j Theall wrote:
>
> Going by the patch I posted a couple of years ago:
> https://sourceforge.net/p/fuse/mailman/message/33033653/
>
> The only hole I see in your patch is that in setattr() you are not updating
> the cached acl if the ATTR_MODE is updated.
Okay, thanks.
> The other major difference is
> that my version uses the get_acl/set_acl inode operations but you use that
> plus the xattr handlers. I'm not up-to-speed on the kernel so I'm not sure
> if you actually need to implement both.
The xattr handlers use the get_acl/set_acl callbacks. Without using the
xattr handlers acl xattr reads won't be pulled from the acl cache, for
one thing.
Thanks,
Seth
>
> Regards,
> Michael Theall
>
> Seth Forshee <seth.forshee@canonical.com> wrote on 06/29/2016 02:07:31 PM:
>
> > From: Seth Forshee <seth.forshee@canonical.com>
> > To: fuse-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org
> > Cc: "Eric W. Biederman" <ebiederm@xmission.com>, Miklos Szeredi
> > <miklos@szeredi.hu>
> > Date: 06/29/2016 02:08 PM
> > Subject: [fuse-devel] [RFC] fuse: Support posix ACLs
> >
> > Eric and I are working towards adding support for fuse mounts in
> > non-init user namespaces. Towards that end we'd like to add ACL support
> > to fuse as this will allow for a cleaner implementation overall. Below
> > is an initial patch to support this. I'd like to get some general
> > feedback on this patch and ask a couple of specific questions.
> >
> > There are some indications that fuse supports ACLs on the userspace side
> > when default_permissions is not used (though I'm not seeing how that
> > works). Will these changes conflict with that support, and if how do we
> > avoid those conflicts?
> >
> > Are there any places where we need to invalidate cached ACLs that aren't
> > covered in the patch?
> >
> > Thanks,
> > Seth
> >
> >
> > diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> > index 8466e122ee62..2f53b0491159 100644
> > --- a/fs/fuse/dir.c
> > +++ b/fs/fuse/dir.c
> > @@ -13,6 +13,8 @@
> > #include <linux/sched.h>
> > #include <linux/namei.h>
> > #include <linux/slab.h>
> > +#include <linux/xattr.h>
> > +#include <linux/posix_acl_xattr.h>
> >
> > static bool fuse_use_readdirplus(struct inode *dir, struct dir_context
> *ctx)
> > {
> > @@ -1061,6 +1063,7 @@ static int fuse_perm_getattr(struct inode
> > *inode, int mask)
> > if (mask & MAY_NOT_BLOCK)
> > return -ECHILD;
> >
> > + forget_all_cached_acls(inode);
> > return fuse_do_getattr(inode, NULL, NULL);
> > }
> >
> > @@ -1719,9 +1722,8 @@ static int fuse_getattr(struct vfsmount *mnt,
> > struct dentry *entry,
> > return fuse_update_attributes(inode, stat, NULL, NULL);
> > }
> >
> > -static int fuse_setxattr(struct dentry *unused, struct inode *inode,
> > - const char *name, const void *value,
> > - size_t size, int flags)
> > +static int fuse_setxattr(struct inode *inode, const char *name,
> > + const void *value, size_t size, int flags)
> > {
> > struct fuse_conn *fc = get_fuse_conn(inode);
> > FUSE_ARGS(args);
> > @@ -1755,8 +1757,8 @@ static int fuse_setxattr(struct dentry
> > *unused, struct inode *inode,
> > return err;
> > }
> >
> > -static ssize_t fuse_getxattr(struct dentry *entry, struct inode *inode,
> > - const char *name, void *value, size_t size)
> > +static ssize_t fuse_getxattr(struct inode *inode, const char *name,
> > + void *value, size_t size)
> > {
> > struct fuse_conn *fc = get_fuse_conn(inode);
> > FUSE_ARGS(args);
> > @@ -1838,9 +1840,8 @@ static ssize_t fuse_listxattr(struct dentry
> > *entry, char *list, size_t size)
> > return ret;
> > }
> >
> > -static int fuse_removexattr(struct dentry *entry, const char *name)
> > +static int fuse_removexattr(struct inode *inode, const char *name)
> > {
> > - struct inode *inode = d_inode(entry);
> > struct fuse_conn *fc = get_fuse_conn(inode);
> > FUSE_ARGS(args);
> > int err;
> > @@ -1865,6 +1866,138 @@ static int fuse_removexattr(struct dentry
> > *entry, const char *name)
> > return err;
> > }
> >
> > +static int fuse_xattr_get(const struct xattr_handler *handler,
> > + struct dentry *dentry, struct inode *inode,
> > + const char *name, void *value, size_t size)
> > +{
> > + return fuse_getxattr(inode, name, value, size);
> > +}
> > +
> > +static int fuse_xattr_set(const struct xattr_handler *handler,
> > + struct dentry *dentry, struct inode *inode,
> > + const char *name, const void *value, size_t size,
> > + int flags)
> > +{
> > + if (!value)
> > + return fuse_removexattr(inode, name);
> > +
> > + return fuse_setxattr(inode, name, value, size, flags);
> > +}
> > +
> > +static const struct xattr_handler fuse_xattr_handler = {
> > + .prefix = "",
> > + .get = fuse_xattr_get,
> > + .set = fuse_xattr_set,
> > +};
> > +
> > +#ifndef CONFIG_POSIX_ACL
> > +static int fuse_xattr_acl_get(const struct xattr_handler *handler,
> > + struct dentry *dentry, struct inode *inode,
> > + const char *name, void *value, size_t size)
> > +{
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +static int fuse_xattr_acl_set(const struct xattr_handler *handler,
> > + struct dentry *dentry, struct inode *inode,
> > + const char *name, const void *value, size_t size,
> > + int flags)
> > +{
> > + return -EOPNOTSUPP;
> > +}
> > +
> > +static const struct xattr_handler fuse_xattr_acl_access_handler = {
> > + .name = XATTR_NAME_POSIX_ACL_ACCESS,
> > + .get = fuse_xattr_acl_get,
> > + .set = fuse_xattr_acl_set,
> > +};
> > +
> > +static const struct xattr_handler fuse_xattr_acl_default_handler = {
> > + .name = XATTR_NAME_POSIX_ACL_DEFAULT,
> > + .get = fuse_xattr_acl_get,
> > + .set = fuse_xattr_acl_set,
> > +};
> > +#endif /* CONFIG_POSIX_ACL */
> > +
> > +const struct xattr_handler *fuse_xattr_handlers[] = {
> > +#ifdef CONFIG_FS_POSIX_ACL
> > + &posix_acl_access_xattr_handler,
> > + &posix_acl_default_xattr_handler,
> > +#else
> > + &fuse_xattr_acl_access_handler,
> > + &fuse_xattr_acl_default_handler,
> > +#endif
> > + &fuse_xattr_handler,
> > +};
> > +
> > +static struct posix_acl *fuse_get_acl(struct inode *inode, int type)
> > +{
> > + int size;
> > + const char *name;
> > + void *value = NULL;
> > + struct posix_acl *acl;
> > +
> > + if (type == ACL_TYPE_ACCESS)
> > + name = XATTR_NAME_POSIX_ACL_ACCESS;
> > + else if (type == ACL_TYPE_DEFAULT)
> > + name = XATTR_NAME_POSIX_ACL_DEFAULT;
> > + else
> > + return ERR_PTR(-EOPNOTSUPP);
> > +
> > + size = fuse_getxattr(inode, name, NULL, 0);
> > + if (size > 0) {
> > + value = kzalloc(size, GFP_KERNEL);
> > + if (!value)
> > + return ERR_PTR(-ENOMEM);
> > + size = fuse_getxattr(inode, name, value, size);
> > + }
> > + if (size > 0) {
> > + acl = posix_acl_from_xattr(inode->i_sb->s_user_ns, value, size);
> > + } else if ((size == 0) || (size == -ENODATA)) {
> > + acl = NULL;
> > + } else {
> > + acl = ERR_PTR(size);
> > + }
> > + kfree(value);
> > +
> > + return acl;
> > +}
> > +
> > +static int fuse_set_acl(struct inode *inode, struct posix_acl *acl,int
> type)
> > +{
> > + const char *name;
> > + int ret;
> > +
> > + if (type == ACL_TYPE_ACCESS)
> > + name = XATTR_NAME_POSIX_ACL_ACCESS;
> > + else if (type == ACL_TYPE_DEFAULT)
> > + name = XATTR_NAME_POSIX_ACL_DEFAULT;
> > + else
> > + return -EINVAL;
> > +
> > + if (acl) {
> > + struct user_namespace *s_user_ns = inode->i_sb->s_user_ns;
> > + size_t size = posix_acl_xattr_size(acl->a_count);
> > + void *value = kmalloc(size, GFP_KERNEL);
> > + if (!value)
> > + return -ENOMEM;
> > +
> > + ret = posix_acl_to_xattr(s_user_ns, acl, value, size);
> > + if (ret < 0) {
> > + kfree(value);
> > + return ret;
> > + }
> > +
> > + ret = fuse_setxattr(inode, name, value, size, 0);
> > + kfree(value);
> > + } else {
> > + ret = fuse_removexattr(inode, name);
> > + }
> > + if (ret == 0)
> > + set_cached_acl(inode, type, acl);
> > + return ret;
> > +}
> > +
> > static const struct inode_operations fuse_dir_inode_operations = {
> > .lookup = fuse_lookup,
> > .mkdir = fuse_mkdir,
> > @@ -1879,10 +2012,12 @@ static const struct inode_operations
> > fuse_dir_inode_operations = {
> > .mknod = fuse_mknod,
> > .permission = fuse_permission,
> > .getattr = fuse_getattr,
> > - .setxattr = fuse_setxattr,
> > - .getxattr = fuse_getxattr,
> > + .setxattr = generic_setxattr,
> > + .getxattr = generic_getxattr,
> > .listxattr = fuse_listxattr,
> > - .removexattr = fuse_removexattr,
> > + .removexattr = generic_removexattr,
> > + .get_acl = fuse_get_acl,
> > + .set_acl = fuse_set_acl,
> > };
> >
> > static const struct file_operations fuse_dir_operations = {
> > @@ -1900,10 +2035,12 @@ static const struct inode_operations
> > fuse_common_inode_operations = {
> > .setattr = fuse_setattr,
> > .permission = fuse_permission,
> > .getattr = fuse_getattr,
> > - .setxattr = fuse_setxattr,
> > - .getxattr = fuse_getxattr,
> > + .setxattr = generic_setxattr,
> > + .getxattr = generic_getxattr,
> > .listxattr = fuse_listxattr,
> > - .removexattr = fuse_removexattr,
> > + .removexattr = generic_removexattr,
> > + .get_acl = fuse_get_acl,
> > + .set_acl = fuse_set_acl,
> > };
> >
> > static const struct inode_operations fuse_symlink_inode_operations = {
> > @@ -1911,10 +2048,12 @@ static const struct inode_operations
> > fuse_symlink_inode_operations = {
> > .get_link = fuse_get_link,
> > .readlink = generic_readlink,
> > .getattr = fuse_getattr,
> > - .setxattr = fuse_setxattr,
> > - .getxattr = fuse_getxattr,
> > + .setxattr = generic_setxattr,
> > + .getxattr = generic_getxattr,
> > .listxattr = fuse_listxattr,
> > - .removexattr = fuse_removexattr,
> > + .removexattr = generic_removexattr,
> > + .get_acl = fuse_get_acl,
> > + .set_acl = fuse_set_acl,
> > };
> >
> > void fuse_init_common(struct inode *inode)
> > diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> > index 9f4c3c82edd6..02c08796051e 100644
> > --- a/fs/fuse/fuse_i.h
> > +++ b/fs/fuse/fuse_i.h
> > @@ -23,6 +23,7 @@
> > #include <linux/poll.h>
> > #include <linux/workqueue.h>
> > #include <linux/kref.h>
> > +#include <linux/xattr.h>
> > #include <linux/pid_namespace.h>
> > #include <linux/user_namespace.h>
> >
> > @@ -693,6 +694,8 @@ extern const struct file_operations
> fuse_dev_operations;
> >
> > extern const struct dentry_operations fuse_dentry_operations;
> >
> > +extern const struct xattr_handler *fuse_xattr_handlers[];
> > +
> > /**
> > * Inode to nodeid comparison.
> > */
> > diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> > index 254f1944ee98..9c1519c269bb 100644
> > --- a/fs/fuse/inode.c
> > +++ b/fs/fuse/inode.c
> > @@ -21,6 +21,7 @@
> > #include <linux/sched.h>
> > #include <linux/exportfs.h>
> > #include <linux/pid_namespace.h>
> > +#include <linux/posix_acl.h>
> >
> > MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
> > MODULE_DESCRIPTION("Filesystem in Userspace");
> > @@ -339,6 +340,7 @@ int fuse_reverse_inval_inode(struct super_block
> > *sb, u64 nodeid,
> > return -ENOENT;
> >
> > fuse_invalidate_attr(inode);
> > + forget_all_cached_acls(inode);
> > if (offset >= 0) {
> > pg_start = offset >> PAGE_SHIFT;
> > if (len <= 0)
> > @@ -1066,6 +1068,7 @@ static int fuse_fill_super(struct super_block
> > *sb, void *data, int silent)
> > }
> > sb->s_magic = FUSE_SUPER_MAGIC;
> > sb->s_op = &fuse_super_operations;
> > + sb->s_xattr = fuse_xattr_handlers;
> > sb->s_maxbytes = MAX_LFS_FILESIZE;
> > sb->s_time_gran = 1;
> > sb->s_export_op = &fuse_export_operations;
> >
> >
> >
> ------------------------------------------------------------------------------
>
> > Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
> > Francisco, CA to explore cutting-edge tech and listen to tech luminaries
> > present their vision of the future. This family event has something for
> > everyone, including kids. Get more information and register today.
> > http://sdm.link/attshape
> > --
> > fuse-devel mailing list
> > To unsubscribe or subscribe, visit https://lists.sourceforge.net/
> > lists/listinfo/fuse-devel
> >
next prev parent reply other threads:[~2016-06-29 20:58 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-29 19:07 [RFC] fuse: Support posix ACLs Seth Forshee
2016-06-29 19:24 ` Michael j Theall
[not found] ` <OFF8F0F486.DB2CEB73-ON86257FE1.006A1FF4-86257FE1.006A9703-8eTO7WVQ4XIsd+ienQ86orlN3bxYEBpz@public.gmane.org>
2016-06-29 19:52 ` Michael j Theall
2016-06-29 21:03 ` [fuse-devel] " Seth Forshee
2016-06-29 21:13 ` Michael j Theall
2016-06-29 20:18 ` [fuse-devel] " Eric W. Biederman
[not found] ` <87vb0rhhpr.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2016-06-29 20:35 ` Michael j Theall
2016-06-30 7:23 ` [fuse-devel] " Jean-Pierre André
2016-06-30 13:07 ` Seth Forshee
2016-06-30 16:25 ` Eric W. Biederman
2016-06-30 16:54 ` Seth Forshee
2016-07-01 19:37 ` Nikolaus Rath
2016-07-01 19:33 ` Nikolaus Rath
2016-07-01 19:49 ` Seth Forshee
2016-06-29 20:56 ` Seth Forshee [this message]
2016-06-30 7:13 ` Jean-Pierre André
2016-07-01 19:29 ` Nikolaus Rath
2016-07-01 19:58 ` Seth Forshee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160629205606.GG53123@ubuntu-hedt \
--to=seth.forshee@canonical.com \
--cc=ebiederm@xmission.com \
--cc=fuse-devel@lists.sourceforge.net \
--cc=linux-fsdevel@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=mtheall@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.