0001
0002
0003
0004
0005
0006 #include <linux/fs.h>
0007 #include <linux/string.h>
0008 #include <linux/xattr.h>
0009 #include <linux/posix_acl_xattr.h>
0010 #include <linux/posix_acl.h>
0011 #include <linux/sched.h>
0012 #include <linux/sched/mm.h>
0013 #include <linux/slab.h>
0014
0015 #include "ctree.h"
0016 #include "btrfs_inode.h"
0017 #include "xattr.h"
0018
0019 struct posix_acl *btrfs_get_acl(struct inode *inode, int type, bool rcu)
0020 {
0021 int size;
0022 const char *name;
0023 char *value = NULL;
0024 struct posix_acl *acl;
0025
0026 if (rcu)
0027 return ERR_PTR(-ECHILD);
0028
0029 switch (type) {
0030 case ACL_TYPE_ACCESS:
0031 name = XATTR_NAME_POSIX_ACL_ACCESS;
0032 break;
0033 case ACL_TYPE_DEFAULT:
0034 name = XATTR_NAME_POSIX_ACL_DEFAULT;
0035 break;
0036 default:
0037 return ERR_PTR(-EINVAL);
0038 }
0039
0040 size = btrfs_getxattr(inode, name, NULL, 0);
0041 if (size > 0) {
0042 value = kzalloc(size, GFP_KERNEL);
0043 if (!value)
0044 return ERR_PTR(-ENOMEM);
0045 size = btrfs_getxattr(inode, name, value, size);
0046 }
0047 if (size > 0)
0048 acl = posix_acl_from_xattr(&init_user_ns, value, size);
0049 else if (size == -ENODATA || size == 0)
0050 acl = NULL;
0051 else
0052 acl = ERR_PTR(size);
0053 kfree(value);
0054
0055 return acl;
0056 }
0057
0058 int __btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode,
0059 struct posix_acl *acl, int type)
0060 {
0061 int ret, size = 0;
0062 const char *name;
0063 char *value = NULL;
0064
0065 switch (type) {
0066 case ACL_TYPE_ACCESS:
0067 name = XATTR_NAME_POSIX_ACL_ACCESS;
0068 break;
0069 case ACL_TYPE_DEFAULT:
0070 if (!S_ISDIR(inode->i_mode))
0071 return acl ? -EINVAL : 0;
0072 name = XATTR_NAME_POSIX_ACL_DEFAULT;
0073 break;
0074 default:
0075 return -EINVAL;
0076 }
0077
0078 if (acl) {
0079 unsigned int nofs_flag;
0080
0081 size = posix_acl_xattr_size(acl->a_count);
0082
0083
0084
0085
0086 nofs_flag = memalloc_nofs_save();
0087 value = kmalloc(size, GFP_KERNEL);
0088 memalloc_nofs_restore(nofs_flag);
0089 if (!value) {
0090 ret = -ENOMEM;
0091 goto out;
0092 }
0093
0094 ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
0095 if (ret < 0)
0096 goto out;
0097 }
0098
0099 if (trans)
0100 ret = btrfs_setxattr(trans, inode, name, value, size, 0);
0101 else
0102 ret = btrfs_setxattr_trans(inode, name, value, size, 0);
0103
0104 out:
0105 kfree(value);
0106
0107 if (!ret)
0108 set_cached_acl(inode, type, acl);
0109
0110 return ret;
0111 }
0112
0113 int btrfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
0114 struct posix_acl *acl, int type)
0115 {
0116 int ret;
0117 umode_t old_mode = inode->i_mode;
0118
0119 if (type == ACL_TYPE_ACCESS && acl) {
0120 ret = posix_acl_update_mode(mnt_userns, inode,
0121 &inode->i_mode, &acl);
0122 if (ret)
0123 return ret;
0124 }
0125 ret = __btrfs_set_acl(NULL, inode, acl, type);
0126 if (ret)
0127 inode->i_mode = old_mode;
0128 return ret;
0129 }