fuse: Support posix ACLs
Subsystems (2)
RFC 1/1 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
fs/fuse/dir.c +155 -16
@@ -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)
fs/fuse/fuse_i.h +3 -0
@@ -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. */
fs/fuse/inode.c +3 -0
@@ -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 <[email protected]>" );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;
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. 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.
Regards,
Michael Theall
Seth Forshee <[email protected]> wrote on 06/29/2016 02:07:31 PM:
Quoted 30 lines
From: Seth Forshee <[email protected]>
To: [email protected], [email protected]
Cc: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>, Miklos Szeredi <[email protected]>
Date: 06/29/2016 02:08 PM
Subject: [fuse-devel] [RFC] fuse: Support posix ACLsEric 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_permissionsis 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,
Sethfs/fuse/dir.c +0
-0
fs/fuse/dir.c line 19
Quoted 7 lines
fs/fuse/dir.c +2
-0@@ -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)
Quoted 140 lines
fs/fuse/dir.c +3
-3{@@ -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);fs/fuse/dir.c +2
-2@@ -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);fs/fuse/dir.c +1
-2@@ -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;fs/fuse/dir.c +88
-0@@ -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 )) {
fs/fuse/dir.c static int fuse_removexattr(struct dentry · line 1967
Quoted 10 lines
fs/fuse/dir.c +10
-0+ 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)
fs/fuse/fuse_i.h extern const struct file_operations
Quoted 101 lines
fs/fuse/dir.c +34
-0+{ +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,fs/fuse/dir.c +5
-3@@ -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_operationsfuse_dir_operations= {fs/fuse/dir.c +5
-3@@ -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_operationsfuse_symlink_inode_operations= {fs/fuse/dir.c +5
-3@@ -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)fs/fuse/fuse_i.h +1
-0@@ -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;
Quoted 37 lines
fs/fuse/fuse_i.h +2
-0extern const struct dentry_operations fuse_dentry_operations; +extern const struct xattr_handler *fuse_xattr_handlers[]; +/** * Inode to nodeid comparison. */ fs/fuse/inode.c +2
-0@@ -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 <[email protected]>" );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)fs/fuse/inode.c +1
-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 ;
Quoted 4 lines
sb->s_export_op = &fuse_export_operations;
------------------------------------------------------------------------------
Quoted 10 lines
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
------------------------------------------------------------------------------
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
Signature · 2 lines
fuse-devel mailing list To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
A message that is not in the archive (sent off-list or not yet received): OFF8F0F486.DB2CEB73-ON86257FE1.006A1FF4-86257FE1.006A9703-8eTO7WVQ4XIsd+ienQ86orlN3bxYEBpz@public.gmane.org
More comments:
My patch does set_cached_acl() in fuse_get_acl(). I would investigate if this is necessary.
Since your patch invalidates the cached acls on getattr(), I would investigate on whether you also need to invalidate cached acls on the entries returned by readdirplus.
Quoted 4 lines
There are some indications that fuse supports ACLs on the userspace side when
default_permissionsis 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?
I wouldn't exactly call it "support". Basically by turning off default_permissions, the fuser server can do what it wants permission-wise. My filesystem turns off default_permissions in order to support ACLs, but as far as fuse is concerned, it is totally oblivious and blindly does what my server says is permitted. That being said, there still lies the problem of checking permissions along the path. The low-level interface only gives you the final inode, which in the case of hard links, the path is ambiguous. This means you can't check each path component for permissions (and the kernel certainly won't! since you turned off default_permissions). Therefore the only "correct" way to implement ACL support on the fuse server is by setting the attr/entry timeout to 0 to force the lookup every time, which defeats many purposes of using fuse in the first place. You can read all the gory details in the thread I linked containing my original patch.
Fortunately, this patch (and mine) allows you to use default_permissions *and* have acl support, meaning permission checks will be performed in kernel for each path component. The extra benefit is that it allows any backing filesystem which supports xattrs to support acls, provided your fuse server has unencumbered privileges for that filesystem.
Regards,
Michael Theall
Michael j Theall/Houston/IBM@IBMUS wrote on 06/29/2016 02:24:14 PM:
Quoted 7 lines
From: Michael j Theall/Houston/IBM@IBMUS
To: Seth Forshee <[email protected]>
Cc: [email protected], [email protected], Miklos-QbrlkLqkJHK1JOh/[email protected], Szeredi <[email protected]>
Date: 06/29/2016 02:37 PM
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLs
Quoted 8 lines
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 theATTR_MODEis updated. 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.
Quoted 5 lines
Regards,
Michael TheallSeth Forshee <[email protected]> wrote on 06/29/2016 02:07:31
PM:
Quoted 8 lines
Quoted 8 lines
From: Seth Forshee <[email protected]>
To: [email protected], [email protected]
Cc: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>, Miklos Szeredi <[email protected]>
Date: 06/29/2016 02:08 PM
Subject: [fuse-devel] [RFC] fuse: Support posix ACLs
Quoted 7 lines
Quoted 7 lines
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
Quoted 5 lines
Quoted 5 lines
when
default_permissionsis 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
Quoted 47 lines
Quoted 11 lines
covered in the patch?
Thanks,
Sethfs/fuse/dir.c +0
-0fs/fuse/dir.c line 19
Quoted 7 lines
fs/fuse/dir.c +2
-0@@ -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)Quoted 28 lines
fs/fuse/dir.c +3
-3{@@ -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);fs/fuse/dir.c +0
-0@@ -1755,8 +1757,8 @@ static int fuse_setxattr(struct dentry *unused, struct inode *inode, return err; }
Quoted 1 line
fs/fuse/dir.c static int fuse_setxattr(struct dentry · line 1759
Quoted 1 line
fs/fuse/dir.c +0
-1-static ssize_t fuse_getxattr(struct dentry *entry, struct inode
*inode,
Quoted 222 lines
Quoted 111 lines
fs/fuse/dir.c +2
-1- 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);fs/fuse/dir.c +1
-2@@ -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;fs/fuse/dir.c +88
-0@@ -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 )) {fs/fuse/dir.c static int fuse_removexattr(struct dentry · line 1967
Quoted 10 lines
fs/fuse/dir.c +10
-0+ 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)
Quoted 100 lines
fs/fuse/dir.c +34
-0+{ +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,fs/fuse/dir.c +5
-3@@ -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_operationsfuse_dir_operations= {fs/fuse/dir.c +5
-3@@ -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_operationsfuse_symlink_inode_operations= {fs/fuse/dir.c +5
-3@@ -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)fs/fuse/fuse_i.h +1
-0@@ -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>
Quoted 1 line
fs/fuse/fuse_i.h extern const struct file_operations
Quoted 1 line
fs/fuse/fuse_i.h +0
-0@@ -693,6 +694,8 @@ extern const struct file_operations
fuse_dev_operations;
Quoted 33 lines
Quoted 33 lines
fs/fuse/fuse_i.h +2
-0extern const struct dentry_operations fuse_dentry_operations; +extern const struct xattr_handler *fuse_xattr_handlers[]; +/** * Inode to nodeid comparison. */ fs/fuse/inode.c +2
-0@@ -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 <[email protected]>" );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)fs/fuse/inode.c +0
-0@@ -1066,6 +1068,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) } sb->s_magic =FUSE_SUPER_MAGIC ;
Quoted 9 lines
Quoted 8 lines
fs/fuse/inode.c +1
-0sb->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;
------------------------------------------------------------------------------
Quoted 2 lines
Quoted 2 lines
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
Quoted 9 lines
Quoted 8 lines
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
------------------------------------------------------------------------------
Quoted 8 lines
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
------------------------------------------------------------------------------
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
Signature · 2 lines
fuse-devel mailing list To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Quoted 5 lines · Michael j Theall
More comments:
My patch does
set_cached_acl()infuse_get_acl(). I would investigate if this is necessary.
Hmm, on the one hand it looks like a lot of filesystems do call it, on the other hand it looks like get_acl is caching it. I'll have to take a closer look.
Quoted 3 lines
Since your patch invalidates the cached acls on
getattr(), I would investigate on whether you also need to invalidate cached acls on the entries returned by readdirplus.
Possibly so. I missed the fact that fuse_direntplus_link might update the inode attributes.
Quoted 20 lines
Quoted 4 lines
There are some indications that fuse supports ACLs on the userspace side when
default_permissionsis 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?I wouldn't exactly call it "support". Basically by turning off
default_permissions, the fuser server can do what it wants permission-wise. My filesystem turns offdefault_permissionsin order to support ACLs, but as far as fuse is concerned, it is totally oblivious and blindly does what my server says is permitted. That being said, there still lies the problem of checking permissions along the path. The low-level interface only gives you the final inode, which in the case of hard links, the path is ambiguous. This means you can't check each path component for permissions (and the kernel certainly won't! since you turned offdefault_permissions). Therefore the only "correct" way to implement ACL support on the fuse server is by setting the attr/entry timeout to 0 to force the lookup every time, which defeats many purposes of using fuse in the first place. You can read all the gory details in the thread I linked containing my original patch.
Quoted 5 lines
Fortunately, this patch (and mine) allows you to use
default_permissions*and* have acl support, meaning permission checks will be performed in kernel for each path component. The extra benefit is that it allows any backing filesystem which supports xattrs to support acls, provided your fuse server has unencumbered privileges for that filesystem.
But if we're going through the posix acl xattr handlers then the acls will be cached. What I worry about is that somehow we could end up in a situation where the cached acls don't match those that the filesystem is using, and userspace sees one thing in response to getfacl but something different is being enforced.
Thanks,
Seth
Quoted 389 lines
Regards,
Michael TheallMichael j Theall/Houston/IBM@IBMUS wrote on 06/29/2016 02:24:14 PM:
Quoted 7 lines
From: Michael j Theall/Houston/IBM@IBMUS
To: Seth Forshee <[email protected]>
Cc: [email protected], [email protected], [email protected], Szeredi <[email protected]>
Date: 06/29/2016 02:37 PM
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLsQuoted 8 lines
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 theATTR_MODEis updated. 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 implementboth.
Quoted 5 lines
Regards,
Michael TheallSeth Forshee <[email protected]> wrote on 06/29/2016 02:07:31
PM:
Quoted 8 lines
Quoted 8 lines
From: Seth Forshee <[email protected]>
To: [email protected], [email protected]
Cc: "Eric W. Biederman" <[email protected]>, Miklos Szeredi <[email protected]>
Date: 06/29/2016 02:08 PM
Subject: [fuse-devel] [RFC] fuse: Support posix ACLsQuoted 7 lines
Quoted 7 lines
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
Quoted 5 lines
Quoted 5 lines
when
default_permissionsis 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
Quoted 47 lines
Quoted 11 lines
covered in the patch?
Thanks,
Sethfs/fuse/dir.c +0
-0fs/fuse/dir.c line 19
Quoted 7 lines
fs/fuse/dir.c +2
-0@@ -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)Quoted 28 lines
fs/fuse/dir.c +3
-3{@@ -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);fs/fuse/dir.c +0
-0@@ -1755,8 +1757,8 @@ static int fuse_setxattr(struct dentry *unused, struct inode *inode, return err; }Quoted 1 line
fs/fuse/dir.c static int fuse_setxattr(struct dentry · line 1759
Quoted 1 line
fs/fuse/dir.c +0
-1-static ssize_t fuse_getxattr(struct dentry *entry, struct inode*inode,
Quoted 222 lines
Quoted 111 lines
fs/fuse/dir.c +2
-1- 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);fs/fuse/dir.c +1
-2@@ -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;fs/fuse/dir.c +88
-0@@ -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 )) {fs/fuse/dir.c static int fuse_removexattr(struct dentry · line 1967
Quoted 10 lines
fs/fuse/dir.c +10
-0+ 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)
Quoted 100 lines
fs/fuse/dir.c +34
-0+{ +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,fs/fuse/dir.c +5
-3@@ -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_operationsfuse_dir_operations= {fs/fuse/dir.c +5
-3@@ -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_operationsfuse_symlink_inode_operations= {fs/fuse/dir.c +5
-3@@ -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)fs/fuse/fuse_i.h +1
-0@@ -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> Quoted 1 line
fs/fuse/fuse_i.h extern const struct file_operations
Quoted 1 line
fs/fuse/fuse_i.h +0
-0@@ -693,6 +694,8 @@ extern const struct file_operations
fuse_dev_operations;Quoted 33 lines
Quoted 33 lines
fs/fuse/fuse_i.h +2
-0extern const struct dentry_operations fuse_dentry_operations; +extern const struct xattr_handler *fuse_xattr_handlers[]; +/** * Inode to nodeid comparison. */ fs/fuse/inode.c +2
-0@@ -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 <[email protected]>" );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)fs/fuse/inode.c +0
-0@@ -1066,6 +1068,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) } sb->s_magic =FUSE_SUPER_MAGIC ;Quoted 9 lines
Quoted 8 lines
fs/fuse/inode.c +1
-0sb->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;------------------------------------------------------------------------------
Quoted 2 lines
Quoted 2 lines
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
Quoted 9 lines
Quoted 8 lines
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------------------------------------------------------------------------------
Quoted 8 lines
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
Seth Forshee <[email protected]> wrote on 06/29/2016 04:03:18 PM:
Quoted 7 lines
From: Seth Forshee <[email protected]>
To: Michael j Theall/Houston/IBM@IBMUS
Cc: [email protected], [email protected], Szeredi <[email protected]>, Miklos-QbrlkLqkJHK1JOh/[email protected]
Date: 06/29/2016 04:03 PM
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLs
Quoted 5 lines
Quoted 4 lines · Michael j Theall
More comments:
My patch does
set_cached_acl()infuse_get_acl(). I would investigate
if
Quoted 6 lines
Quoted 1 line
this is necessary.
Hmm, on the one hand it looks like a lot of filesystems do call it, on the other hand it looks like
get_aclis caching it. I'll have to take a closer look.
Quoted 8 lines
Quoted 3 lines
Since your patch invalidates the cached acls on
getattr(), I would investigate on whether you also need to invalidate cached acls on the entries returned by readdirplus.Possibly so. I missed the fact that
fuse_direntplus_linkmight update the inode attributes.Quoted 1 line
Quoted 1 line
There are some indications that fuse supports ACLs on the userspace
side
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
when
default_permissionsis not used (though I'm not seeing how that works). Will these changes conflict with that support, and if how do
we
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
avoid those conflicts?
I wouldn't exactly call it "support". Basically by turning off
default_permissions, the fuser server can do what it wants
permission-wise.
Quoted 1 line
Quoted 1 line
My filesystem turns off
default_permissionsin order to support ACLs,
but
Quoted 1 line
Quoted 1 line
as far as fuse is concerned, it is totally oblivious and blindly does
what
Quoted 1 line
Quoted 1 line
my server says is permitted. That being said, there still lies the
problem
Quoted 1 line
Quoted 1 line
of checking permissions along the path. The low-level interface only
gives
Quoted 2 lines
Quoted 2 lines
you the final inode, which in the case of hard links, the path is ambiguous. This means you can't check each path component for
permissions
Quoted 1 line
Quoted 1 line
(and the kernel certainly won't! since you turned off
default_permissions).
Quoted 2 lines
Quoted 2 lines
Therefore the only "correct" way to implement ACL support on the fuse server is by setting the attr/entry timeout to 0 to force the lookup
every
Quoted 1 line
Quoted 1 line
time, which defeats many purposes of using fuse in the first place. You
can
Quoted 4 lines
Quoted 4 lines
read all the gory details in the thread I linked containing my original patch.
Fortunately, this patch (and mine) allows you to use
default_permissions
Quoted 11 lines
Quoted 4 lines
*and* have acl support, meaning permission checks will be performed in kernel for each path component. The extra benefit is that it allows any backing filesystem which supports xattrs to support acls, provided your fuse server has unencumbered privileges for that filesystem.
But if we're going through the posix acl xattr handlers then the acls will be cached. What I worry about is that somehow we could end up in a situation where the cached acls don't match those that the filesystem is using, and userspace sees one thing in response to getfacl but something different is being enforced.
This isn't any different from the unix permissions. This is the price you pay for caching any attributes. If it's a problem, the server can reduce the cache timeout, or eliminate caching by setting the timeout to 0.
Regards,
Michael Theall
Quoted 30 lines
Thanks,
SethQuoted 27 lines
Regards,
Michael TheallMichael j Theall/Houston/IBM@IBMUS wrote on 06/29/2016 02:24:14 PM:
Quoted 7 lines
From: Michael j Theall/Houston/IBM@IBMUS
To: Seth Forshee <[email protected]>
Cc: [email protected], [email protected], Miklos-QbrlkLqkJHK1JOh/[email protected], Szeredi <[email protected]>
Date: 06/29/2016 02:37 PM
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLsQuoted 8 lines
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 theATTR_MODEis updated. 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 implementboth.
Quoted 5 lines
Regards,
Michael TheallSeth Forshee <[email protected]> wrote on 06/29/2016
02:07:31
Quoted 11 lines
Quoted 11 lines
PM:
Quoted 10 lines
Quoted 10 lines
From: Seth Forshee <[email protected]>
To: [email protected], [email protected]
Cc: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>, Miklos Szeredi <[email protected]>
Date: 06/29/2016 02:08 PM
Subject: [fuse-devel] [RFC] fuse: Support posix ACLsEric 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
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
to fuse as this will allow for a cleaner implementation overall.
Below
Quoted 6 lines
Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
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
Quoted 1 line
Quoted 1 line
when
default_permissionsis not used (though I'm not seeing how
that
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
works). Will these changes conflict with that support, and if how
do we
Quoted 33 lines
Quoted 33 lines
Quoted 3 lines
Quoted 3 lines
avoid those conflicts?
Are there any places where we need to invalidate cached ACLs that
aren't
Quoted 29 lines
Quoted 11 lines
covered in the patch?
Thanks,
Sethfs/fuse/dir.c +0
-0fs/fuse/dir.c line 19
Quoted 7 lines
fs/fuse/dir.c +2
-0@@ -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)Quoted 10 lines
fs/fuse/dir.c +1
-0{@@ -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 ); }
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
fs/fuse/dir.c static int fuse_getattr(struct vfsmount *mnt, · line 1723
Quoted 6 lines
fs/fuse/dir.c +0
-1@@ -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,
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
fs/fuse/dir.c +2
-2- 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);fs/fuse/dir.c +0
-0@@ -1755,8 +1757,8 @@ static int fuse_setxattr(struct dentry *unused, struct inode *inode, return err; }
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
fs/fuse/dir.c static int fuse_setxattr(struct dentry · line 1759
Quoted 1 line
fs/fuse/dir.c +0
-1-static ssize_t fuse_getxattr(struct dentry *entry, struct inode*inode,
Quoted 2 lines
Quoted 2 lines
fs/fuse/dir.c +1
-1- const char *name, void *value, size_t size) +static ssize_t fuse_getxattr(struct inode *inode, const char
*name,
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
fs/fuse/dir.c static ssize_t fuse_listxattr(struct dentry · line 1842
Quoted 10 lines
fs/fuse/dir.c +1
-0+ void *value, size_t size) {struct fuse_conn *fc =get_fuse_conn (inode);FUSE_ARGS(args);fs/fuse/dir.c +0
-1@@ -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)
Quoted 44 lines
Quoted 44 lines
Quoted 44 lines
Quoted 44 lines
fs/fuse/dir.c +1
-1+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;fs/fuse/dir.c +33
-0@@ -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,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
fs/fuse/dir.c static int fuse_removexattr(struct dentry *entry, const char *name)
Quoted 8 lines
fs/fuse/dir.c +8
-0+ 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 =
{
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
fs/fuse/dir.c static int fuse_removexattr(struct dentry *entry, const char *name)
Quoted 6 lines
fs/fuse/dir.c +6
-0+ .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 =
{
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
fs/fuse/dir.c +10
-0+ .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,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
fs/fuse/dir.c static int fuse_removexattr(struct dentry *entry, const char *name)
Quoted 8 lines
fs/fuse/dir.c +8
-0+#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)
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
fs/fuse/dir.c +14
-0+{ +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 );
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
fs/fuse/dir.c static int fuse_removexattr(struct dentry *entry, const char *name)
Quoted 8 lines
fs/fuse/dir.c +8
-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);
Quoted 82 lines
Quoted 82 lines
Quoted 82 lines
fs/fuse/dir.c static int fuse_removexattr(struct dentry *entry, const char *name)
Quoted 11 lines
fs/fuse/dir.c +11
-0+ }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)
Quoted 70 lines
fs/fuse/dir.c +34
-0+{ +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,fs/fuse/dir.c +5
-3@@ -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_operationsfuse_dir_operations= {fs/fuse/dir.c +5
-3@@ -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, };
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
static const struct
inode_operationsfuse_symlink_inode_operations
= {
Quoted 66 lines
Quoted 66 lines
Quoted 29 lines
Quoted 29 lines
fs/fuse/dir.c +5
-3@@ -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)fs/fuse/fuse_i.h +1
-0@@ -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> Quoted 1 line
fs/fuse/fuse_i.h extern const struct file_operations
Quoted 1 line
fs/fuse/fuse_i.h +0
-0@@ -693,6 +694,8 @@ extern const struct file_operations
fuse_dev_operations;Quoted 35 lines
Quoted 35 lines
fs/fuse/fuse_i.h +2
-0extern const struct dentry_operations fuse_dentry_operations; +extern const struct xattr_handler *fuse_xattr_handlers[]; +/** * Inode to nodeid comparison. */ fs/fuse/inode.c +2
-0@@ -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 <[email protected]>" );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)fs/fuse/inode.c +1
-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;
Quoted 9 lines
Quoted 8 lines
Quoted 7 lines
Quoted 6 lines
fs/fuse/inode.c +0
-0sb->s_maxbytes =MAX_LFS_FILESIZE ; sb->s_time_gran =1 ;sb->s_export_op = &fuse_export_operations;
------------------------------------------------------------------------------
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in
San
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Francisco, CA to explore cutting-edge tech and listen to tech
luminaries
Quoted 1 line
Quoted 1 line
present their vision of the future. This family event has something
for
Quoted 10 lines
Quoted 9 lines
Quoted 8 lines
Quoted 7 lines
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
------------------------------------------------------------------------------
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in
San
Quoted 1 line
Quoted 1 line
Quoted 1 line
Francisco, CA to explore cutting-edge tech and listen to tech
luminaries
Quoted 1 line
Quoted 1 line
Quoted 1 line
present their vision of the future. This family event has something
for
Quoted 6 lines
Quoted 5 lines
Quoted 5 lines
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
------------------------------------------------------------------------------
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
Signature · 2 lines
fuse-devel mailing list To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.
That makes an interesting question. Is it desirable to keep inode->i_mode in sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?
The fact that MS_POSIXACL is set indicates that fuse supports posix acls. Have posix acls never worked then?
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
Hi,
MS_POSIXACL is only set so that fuse sends doesn't mask the mode sent with open/mkdir/mknod. This is necessary to properly implement POSIX ACLs, along with the umask value which is also sent with these requests.
Regards,
Michael Theall
ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected] (Eric W. Biederman) wrote on 06/29/2016 03:18:24 PM:
Quoted 20 lines
From: ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected] (Eric W. Biederman)
To: Michael j Theall/Houston/IBM@IBMUS
Cc: Seth Forshee <[email protected]>, fuse- [email protected], [email protected], Miklos Szeredi <[email protected]>
Date: 06/29/2016 03:30 PM
Subject: Re: [fuse-devel] [RFC] fuse: Support posix ACLsQuoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.
Quoted 9 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?The fact that
MS_POSIXACLis set indicates that fuse supports posix acls. Have posix acls never worked then?Eric
------------------------------------------------------------------------------
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
Signature · 2 lines
fuse-devel mailing list To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel
Quoted 12 lines · [email protected] (Eric W. Biederman) wrote:
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.
Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?
Using a former implementation of ACLs within fuse at the kernel level, I got the result below.
File systems expect consistency.
# Using the low level interface of fuse, with use of ACLs
# intended to be checked in the kernel, but not related to # access control rm -rf trydir mkdir trydir echo file > trydir/file ls -l trydir/file setfacl -m 'u::7,g::5,o::5' trydir/file ls -l trydir/file sleep 1 ls -l trydir/file
-rw-r--r-- 1 root root 5 2009-09-12 12:02 trydir/file -rw-r--r-- 1 root root 5 2009-09-12 12:02 trydir/file -rwxr-xr-x 1 root root 5 2009-09-12 12:02 trydir/file
Jean-Pierre
Quoted 12 lines · Eric W. Biederman
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.
Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?
My first blush opinion is that the kernel should take care of this, not the filesystems. Then a fuse filesystem which supports xattrs gets acl support for free. Otherwise if a filesystem supports xattrs but not acls internally, we have no way of knowing that in the kernel and they get out of sync.
However if some filesystems are already doing this internally then we have redundancy. Presumably this would be harmless aside from the wasted effort.
Seth
Quoted 23 lines · Seth Forshee
Quoted 12 lines · Eric W. Biederman
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?My first blush opinion is that the kernel should take care of this, not the filesystems. Then a fuse filesystem which supports xattrs gets acl support for free. Otherwise if a filesystem supports xattrs but not acls internally, we have no way of knowing that in the kernel and they get out of sync.
Quoted 3 lines
However if some filesystems are already doing this internally then we have redundancy. Presumably this would be harmless aside from the wasted effort.
Which means that in set_acl we need to something like:
if (type == ACL_TYPE_ACCESS) {
struct iattr attr;
attr.ia_valid = ATTR_MODE;
attr.ia_mode = inode->i_mode;
ret = posix_acl_equiv_mode(acl, &attr.ia_mode);
if (ret < 0)
return ret;
if (ret == 0)
acl = NULL;
if (attr.ia_mode != inode->i_mode) {
ret = fuse_do_setattr(inode, &attr, NULL);
if (ret < 0)
return ret;
}
}In fuse_setattr should wind up looking something like:
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
struct inode *inode = d_inode(entry);
int ret;
if (!fuse_allow_current_process(get_fuse_conn(inode)))
return -EACCES;
if (attr->ia_valid & ATTR_FILE)
ret = fuse_do_setattr(inode, attr, attr->ia_file);
else
ret = fuse_do_setattr(inode, attr, NULL);
if (ret == 0 && attr->ia_valid & ATTR_MODE)
ret = posix_acl_chmod(inode, inode->i_mode);
return ret;
}That should be enough to keep everything in sync with the existing fuse protocol. And then fuse filesystems won't have to care in general about the contents of acls (unless they choose to care).
Eric
Quoted 67 lines · Eric W. Biederman
Quoted 23 lines · Seth Forshee
Quoted 12 lines · Eric W. Biederman
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?My first blush opinion is that the kernel should take care of this, not the filesystems. Then a fuse filesystem which supports xattrs gets acl support for free. Otherwise if a filesystem supports xattrs but not acls internally, we have no way of knowing that in the kernel and they get out of sync.
Quoted 3 lines
However if some filesystems are already doing this internally then we have redundancy. Presumably this would be harmless aside from the wasted effort.
Which means that in
set_aclwe need to something like:if (type == ACL_TYPE_ACCESS) { struct iattr attr; attr.ia_valid = ATTR_MODE; attr.ia_mode = inode->i_mode; ret = posix_acl_equiv_mode(acl, &attr.ia_mode); if (ret < 0) return ret; if (ret == 0) acl = NULL; if (attr.ia_mode != inode->i_mode) { ret = fuse_do_setattr(inode, &attr, NULL); if (ret < 0) return ret; } }In
fuse_setattrshould wind up looking something like:static int
fuse_setattr(struct dentry *entry, struct iattr *attr){ struct inode *inode = d_inode(entry); int ret; if (!fuse_allow_current_process(get_fuse_conn(inode))) return -EACCES; if (attr->ia_valid & ATTR_FILE) ret = fuse_do_setattr(inode, attr, attr->ia_file); else ret = fuse_do_setattr(inode, attr, NULL); if (ret == 0 && attr->ia_valid & ATTR_MODE) ret = posix_acl_chmod(inode, inode->i_mode); return ret; }
Quoted 3 lines
That should be enough to keep everything in sync with the existing fuse protocol. And then fuse filesystems won't have to care in general about the contents of acls (unless they choose to care).
Yes, I've already written pretty much the same code and am attempting to test it. The problem I'm having is finding a good filesystem to test with. fusexmp works but is probably unfair as the underlying filesystem is handling the acls and updating the mode. I haven't found any filesystem yet that fully supports xattrs but doesn't do something special with the posix acl xattrs.
Can anyone suggest a good filesystem for me to test with?
Thanks,
Seth
Quoted 8 lines · Seth Forshee
Yes, I've already written pretty much the same code and am attempting to test it. The problem I'm having is finding a good filesystem to test with. fusexmp works but is probably unfair as the underlying filesystem is handling the acls and updating the mode. I haven't found any filesystem yet that fully supports xattrs but doesn't do something special with the posix acl xattrs.
Can anyone suggest a good filesystem for me to test with?
S3QL should do it with a small patch - at the moment it deliberately returns an error when the kernel tries to acces system.posix_acl*. This is done specifically so that the kernel doesn't think that ACLs are supported when they actually aren't (because of the missing synchronization with the permission bits).
Download from https://bitbucket.org/nikratio/s3ql/ and comment out the check in src/s3ql/fs.py:getxattr():
# http://code.google.com/p/s3ql/issues/detail?id=385
elif name in (b'system.posix_acl_access',
b'system.posix_acl_default'):
raise FUSEError(ACL_ERRNO)
Best,
-Nikolaus
Signature · 4 lines
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«Quoted 12 lines · On Jun 29 2016, [email protected] (Eric W. Biederman) wrote:
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.
Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?
A FUSE file system should be able to support ACLs without requiring the file system process to do more than support extended attributes. I believe this means that the kernel should keep i_mode and the ACLs in sync -- it would be a rather bug prone and redundant for each FUSE file system to implement its own parser for format in which the ACLs are stored in xattrs.
Best,
-Nikolaus
Signature · 4 lines
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«Quoted 17 lines · Nikolaus Rath
Quoted 12 lines · On Jun 29 2016, [email protected] (Eric W. Biederman) wrote:
Quoted 9 lines · Michael j Theall
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 theATTR_MODEis updated. 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.Quoted 3 lines
That makes an interesting question. Is it desirable to keep
inode->i_modein sync with the posix acls in fuse or should a filesystem that supports posix acls worry about that?
Quoted 6 lines
A FUSE file system should be able to support ACLs without requiring the file system process to do more than support extended attributes. I believe this means that the kernel should keep
i_modeand the ACLs in sync -- it would be a rather bug prone and redundant for each FUSE file system to implement its own parser for format in which the ACLs are stored in xattrs.
The most recent patch I posted keeps them in sync.
Thanks,
Seth
Quoted 6 lines · Michael j Theall
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 theATTR_MODEis updated.
Okay, thanks.
Quoted 4 lines
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
Quoted 350 lines
Regards,
Michael TheallSeth Forshee <[email protected]> wrote on 06/29/2016 02:07:31 PM:
Quoted 30 lines
From: Seth Forshee <[email protected]>
To: [email protected], [email protected]
Cc: "Eric W. Biederman" <[email protected]>, Miklos Szeredi <[email protected]>
Date: 06/29/2016 02:08 PM
Subject: [fuse-devel] [RFC] fuse: Support posix ACLsEric 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_permissionsis 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,
Sethfs/fuse/dir.c +0
-0fs/fuse/dir.c line 19
Quoted 7 lines
fs/fuse/dir.c +2
-0@@ -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)
Quoted 140 lines
fs/fuse/dir.c +3
-3{@@ -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);fs/fuse/dir.c +2
-2@@ -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);fs/fuse/dir.c +1
-2@@ -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;fs/fuse/dir.c +88
-0@@ -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 )) {fs/fuse/dir.c static int fuse_removexattr(struct dentry · line 1967
Quoted 10 lines
fs/fuse/dir.c +10
-0+ acl =NULL ; + }else { + acl =ERR_PTR (size); + } +kfree (value); + +return acl; +} + +static int fuse_set_acl(struct inode *inode, struct posix_acl *acl,inttype)
fs/fuse/fuse_i.h extern const struct file_operations
Quoted 101 lines
fs/fuse/dir.c +34
-0+{ +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,fs/fuse/dir.c +5
-3@@ -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_operationsfuse_dir_operations= {fs/fuse/dir.c +5
-3@@ -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_operationsfuse_symlink_inode_operations= {fs/fuse/dir.c +5
-3@@ -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)fs/fuse/fuse_i.h +1
-0@@ -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;Quoted 37 lines
fs/fuse/fuse_i.h +2
-0extern const struct dentry_operations fuse_dentry_operations; +extern const struct xattr_handler *fuse_xattr_handlers[]; +/** * Inode to nodeid comparison. */ fs/fuse/inode.c +2
-0@@ -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 <[email protected]>" );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)fs/fuse/inode.c +1
-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 ;Quoted 4 lines
sb->s_export_op = &fuse_export_operations;------------------------------------------------------------------------------
Quoted 10 lines
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
Quoted 3 lines · Seth Forshee
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
My best wishes go with you.
Quoted 7 lines
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_permissionsis 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?
ntfs-3g has both variants implemented. When supporting ACLs within the userspace, it does not set default_permissions, and it uses null cache timeouts.
When expecting ACLs supported at the kernel level, it sets default_permissions and it uses non_null cache timeouts.
It sets FUSE_CAP_DONT_MASK in both cases.
I would expect default_permissions to make a clear divide between those conditions, avoiding any conflicts.
Jean-Pierre
Quoted 11 lines · Seth Forshee
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_permissionsis 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?
I think as long as the kernel interprets ACLs only if default_permission is used, you should be fine.
Best,
-Nikolaus
Signature · 4 lines
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«Quoted 7 lines · Nikolaus Rath
Quoted 6 lines · Seth Forshee
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.
Quoted 7 lines
Quoted 5 lines
There are some indications that fuse supports ACLs on the userspace side when
default_permissionsis 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?I think as long as the kernel interprets ACLs only if
default_permissionis used, you should be fine.
With !default_permission fuse never calls generic_permission so the kernel won't enforce the acls regardless. For the purpose of user namespace mounts it's still useful if the kernel intercepts them so that the posix acl layer can do the uid/gid translation before passing it to the filesystem. The xattrs still get sent on to the filesystem, however cached acls if present would be used to satisfy reads of the acl xatts.
Thanks,
Seth