Branch data Line data Source code
1 : : /* 2 : : * FUSE: Filesystem in Userspace 3 : : * Copyright (C) 2016 Canonical Ltd. <seth.forshee@canonical.com> 4 : : * 5 : : * This program can be distributed under the terms of the GNU GPL. 6 : : * See the file COPYING. 7 : : */ 8 : : 9 : : #include "fuse_i.h" 10 : : 11 : : #include <linux/posix_acl.h> 12 : : #include <linux/posix_acl_xattr.h> 13 : : 14 : 0 : struct posix_acl *fuse_get_acl(struct inode *inode, int type) 15 : : { 16 : : struct fuse_conn *fc = get_fuse_conn(inode); 17 : : int size; 18 : : const char *name; 19 : : void *value = NULL; 20 : : struct posix_acl *acl; 21 : : 22 : 0 : if (!fc->posix_acl || fc->no_getxattr) 23 : : return NULL; 24 : : 25 : 0 : if (type == ACL_TYPE_ACCESS) 26 : : name = XATTR_NAME_POSIX_ACL_ACCESS; 27 : 0 : else if (type == ACL_TYPE_DEFAULT) 28 : : name = XATTR_NAME_POSIX_ACL_DEFAULT; 29 : : else 30 : : return ERR_PTR(-EOPNOTSUPP); 31 : : 32 : : value = kmalloc(PAGE_SIZE, GFP_KERNEL); 33 : 0 : if (!value) 34 : : return ERR_PTR(-ENOMEM); 35 : 0 : size = fuse_getxattr(inode, name, value, PAGE_SIZE); 36 : 0 : if (size > 0) 37 : 0 : acl = posix_acl_from_xattr(fc->user_ns, value, size); 38 : 0 : else if ((size == 0) || (size == -ENODATA) || 39 : 0 : (size == -EOPNOTSUPP && fc->no_getxattr)) 40 : : acl = NULL; 41 : 0 : else if (size == -ERANGE) 42 : : acl = ERR_PTR(-E2BIG); 43 : : else 44 : : acl = ERR_PTR(size); 45 : : 46 : 0 : kfree(value); 47 : 0 : return acl; 48 : : } 49 : : 50 : 0 : int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type) 51 : : { 52 : : struct fuse_conn *fc = get_fuse_conn(inode); 53 : : const char *name; 54 : : int ret; 55 : : 56 : 0 : if (!fc->posix_acl || fc->no_setxattr) 57 : : return -EOPNOTSUPP; 58 : : 59 : 0 : if (type == ACL_TYPE_ACCESS) 60 : : name = XATTR_NAME_POSIX_ACL_ACCESS; 61 : 0 : else if (type == ACL_TYPE_DEFAULT) 62 : : name = XATTR_NAME_POSIX_ACL_DEFAULT; 63 : : else 64 : : return -EINVAL; 65 : : 66 : 0 : if (acl) { 67 : : /* 68 : : * Fuse userspace is responsible for updating access 69 : : * permissions in the inode, if needed. fuse_setxattr 70 : : * invalidates the inode attributes, which will force 71 : : * them to be refreshed the next time they are used, 72 : : * and it also updates i_ctime. 73 : : */ 74 : 0 : size_t size = posix_acl_xattr_size(acl->a_count); 75 : : void *value; 76 : : 77 : 0 : if (size > PAGE_SIZE) 78 : : return -E2BIG; 79 : : 80 : : value = kmalloc(size, GFP_KERNEL); 81 : 0 : if (!value) 82 : : return -ENOMEM; 83 : : 84 : 0 : ret = posix_acl_to_xattr(fc->user_ns, acl, value, size); 85 : 0 : if (ret < 0) { 86 : 0 : kfree(value); 87 : 0 : return ret; 88 : : } 89 : : 90 : 0 : ret = fuse_setxattr(inode, name, value, size, 0); 91 : 0 : kfree(value); 92 : : } else { 93 : 0 : ret = fuse_removexattr(inode, name); 94 : : } 95 : 0 : forget_all_cached_acls(inode); 96 : 0 : fuse_invalidate_attr(inode); 97 : : 98 : 0 : return ret; 99 : : }