0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fuse_i.h"
0010
0011 #include <linux/xattr.h>
0012 #include <linux/posix_acl_xattr.h>
0013
0014 int fuse_setxattr(struct inode *inode, const char *name, const void *value,
0015 size_t size, int flags, unsigned int extra_flags)
0016 {
0017 struct fuse_mount *fm = get_fuse_mount(inode);
0018 FUSE_ARGS(args);
0019 struct fuse_setxattr_in inarg;
0020 int err;
0021
0022 if (fm->fc->no_setxattr)
0023 return -EOPNOTSUPP;
0024
0025 memset(&inarg, 0, sizeof(inarg));
0026 inarg.size = size;
0027 inarg.flags = flags;
0028 inarg.setxattr_flags = extra_flags;
0029
0030 args.opcode = FUSE_SETXATTR;
0031 args.nodeid = get_node_id(inode);
0032 args.in_numargs = 3;
0033 args.in_args[0].size = fm->fc->setxattr_ext ?
0034 sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
0035 args.in_args[0].value = &inarg;
0036 args.in_args[1].size = strlen(name) + 1;
0037 args.in_args[1].value = name;
0038 args.in_args[2].size = size;
0039 args.in_args[2].value = value;
0040 err = fuse_simple_request(fm, &args);
0041 if (err == -ENOSYS) {
0042 fm->fc->no_setxattr = 1;
0043 err = -EOPNOTSUPP;
0044 }
0045 if (!err)
0046 fuse_update_ctime(inode);
0047
0048 return err;
0049 }
0050
0051 ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
0052 size_t size)
0053 {
0054 struct fuse_mount *fm = get_fuse_mount(inode);
0055 FUSE_ARGS(args);
0056 struct fuse_getxattr_in inarg;
0057 struct fuse_getxattr_out outarg;
0058 ssize_t ret;
0059
0060 if (fm->fc->no_getxattr)
0061 return -EOPNOTSUPP;
0062
0063 memset(&inarg, 0, sizeof(inarg));
0064 inarg.size = size;
0065 args.opcode = FUSE_GETXATTR;
0066 args.nodeid = get_node_id(inode);
0067 args.in_numargs = 2;
0068 args.in_args[0].size = sizeof(inarg);
0069 args.in_args[0].value = &inarg;
0070 args.in_args[1].size = strlen(name) + 1;
0071 args.in_args[1].value = name;
0072
0073 args.out_numargs = 1;
0074 if (size) {
0075 args.out_argvar = true;
0076 args.out_args[0].size = size;
0077 args.out_args[0].value = value;
0078 } else {
0079 args.out_args[0].size = sizeof(outarg);
0080 args.out_args[0].value = &outarg;
0081 }
0082 ret = fuse_simple_request(fm, &args);
0083 if (!ret && !size)
0084 ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
0085 if (ret == -ENOSYS) {
0086 fm->fc->no_getxattr = 1;
0087 ret = -EOPNOTSUPP;
0088 }
0089 return ret;
0090 }
0091
0092 static int fuse_verify_xattr_list(char *list, size_t size)
0093 {
0094 size_t origsize = size;
0095
0096 while (size) {
0097 size_t thislen = strnlen(list, size);
0098
0099 if (!thislen || thislen == size)
0100 return -EIO;
0101
0102 size -= thislen + 1;
0103 list += thislen + 1;
0104 }
0105
0106 return origsize;
0107 }
0108
0109 ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
0110 {
0111 struct inode *inode = d_inode(entry);
0112 struct fuse_mount *fm = get_fuse_mount(inode);
0113 FUSE_ARGS(args);
0114 struct fuse_getxattr_in inarg;
0115 struct fuse_getxattr_out outarg;
0116 ssize_t ret;
0117
0118 if (fuse_is_bad(inode))
0119 return -EIO;
0120
0121 if (!fuse_allow_current_process(fm->fc))
0122 return -EACCES;
0123
0124 if (fm->fc->no_listxattr)
0125 return -EOPNOTSUPP;
0126
0127 memset(&inarg, 0, sizeof(inarg));
0128 inarg.size = size;
0129 args.opcode = FUSE_LISTXATTR;
0130 args.nodeid = get_node_id(inode);
0131 args.in_numargs = 1;
0132 args.in_args[0].size = sizeof(inarg);
0133 args.in_args[0].value = &inarg;
0134
0135 args.out_numargs = 1;
0136 if (size) {
0137 args.out_argvar = true;
0138 args.out_args[0].size = size;
0139 args.out_args[0].value = list;
0140 } else {
0141 args.out_args[0].size = sizeof(outarg);
0142 args.out_args[0].value = &outarg;
0143 }
0144 ret = fuse_simple_request(fm, &args);
0145 if (!ret && !size)
0146 ret = min_t(ssize_t, outarg.size, XATTR_LIST_MAX);
0147 if (ret > 0 && size)
0148 ret = fuse_verify_xattr_list(list, ret);
0149 if (ret == -ENOSYS) {
0150 fm->fc->no_listxattr = 1;
0151 ret = -EOPNOTSUPP;
0152 }
0153 return ret;
0154 }
0155
0156 int fuse_removexattr(struct inode *inode, const char *name)
0157 {
0158 struct fuse_mount *fm = get_fuse_mount(inode);
0159 FUSE_ARGS(args);
0160 int err;
0161
0162 if (fm->fc->no_removexattr)
0163 return -EOPNOTSUPP;
0164
0165 args.opcode = FUSE_REMOVEXATTR;
0166 args.nodeid = get_node_id(inode);
0167 args.in_numargs = 1;
0168 args.in_args[0].size = strlen(name) + 1;
0169 args.in_args[0].value = name;
0170 err = fuse_simple_request(fm, &args);
0171 if (err == -ENOSYS) {
0172 fm->fc->no_removexattr = 1;
0173 err = -EOPNOTSUPP;
0174 }
0175 if (!err)
0176 fuse_update_ctime(inode);
0177
0178 return err;
0179 }
0180
0181 static int fuse_xattr_get(const struct xattr_handler *handler,
0182 struct dentry *dentry, struct inode *inode,
0183 const char *name, void *value, size_t size)
0184 {
0185 if (fuse_is_bad(inode))
0186 return -EIO;
0187
0188 return fuse_getxattr(inode, name, value, size);
0189 }
0190
0191 static int fuse_xattr_set(const struct xattr_handler *handler,
0192 struct user_namespace *mnt_userns,
0193 struct dentry *dentry, struct inode *inode,
0194 const char *name, const void *value, size_t size,
0195 int flags)
0196 {
0197 if (fuse_is_bad(inode))
0198 return -EIO;
0199
0200 if (!value)
0201 return fuse_removexattr(inode, name);
0202
0203 return fuse_setxattr(inode, name, value, size, flags, 0);
0204 }
0205
0206 static bool no_xattr_list(struct dentry *dentry)
0207 {
0208 return false;
0209 }
0210
0211 static int no_xattr_get(const struct xattr_handler *handler,
0212 struct dentry *dentry, struct inode *inode,
0213 const char *name, void *value, size_t size)
0214 {
0215 return -EOPNOTSUPP;
0216 }
0217
0218 static int no_xattr_set(const struct xattr_handler *handler,
0219 struct user_namespace *mnt_userns,
0220 struct dentry *dentry, struct inode *nodee,
0221 const char *name, const void *value,
0222 size_t size, int flags)
0223 {
0224 return -EOPNOTSUPP;
0225 }
0226
0227 static const struct xattr_handler fuse_xattr_handler = {
0228 .prefix = "",
0229 .get = fuse_xattr_get,
0230 .set = fuse_xattr_set,
0231 };
0232
0233 const struct xattr_handler *fuse_xattr_handlers[] = {
0234 &fuse_xattr_handler,
0235 NULL
0236 };
0237
0238 const struct xattr_handler *fuse_acl_xattr_handlers[] = {
0239 &posix_acl_access_xattr_handler,
0240 &posix_acl_default_xattr_handler,
0241 &fuse_xattr_handler,
0242 NULL
0243 };
0244
0245 static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
0246 .name = XATTR_NAME_POSIX_ACL_ACCESS,
0247 .flags = ACL_TYPE_ACCESS,
0248 .list = no_xattr_list,
0249 .get = no_xattr_get,
0250 .set = no_xattr_set,
0251 };
0252
0253 static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
0254 .name = XATTR_NAME_POSIX_ACL_DEFAULT,
0255 .flags = ACL_TYPE_ACCESS,
0256 .list = no_xattr_list,
0257 .get = no_xattr_get,
0258 .set = no_xattr_set,
0259 };
0260
0261 const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
0262 &fuse_no_acl_access_xattr_handler,
0263 &fuse_no_acl_default_xattr_handler,
0264 &fuse_xattr_handler,
0265 NULL
0266 };