Fuse currently lacks comprehensive support for posix ACLs, but
some fuse filesystems process the acl xattrs internally. For this
to continue to work the ids within the xattrs need to be mapped
into s_user_ns when written to the filesystem and mapped from
s_user_ns when read.
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
{
struct fuse_conn *fc = get_fuse_conn(inode);
FUSE_ARGS(args);
{
struct fuse_conn *fc = get_fuse_conn(inode);
FUSE_ARGS(args);
struct fuse_setxattr_in inarg;
int err;
if (fc->no_setxattr)
return -EOPNOTSUPP;
struct fuse_setxattr_in inarg;
int err;
if (fc->no_setxattr)
return -EOPNOTSUPP;
+ if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
+ !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT)) {
+ buf = kmemdup(value, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ err = posix_acl_fix_xattr_userns(inode->i_sb->s_user_ns,
+ &init_user_ns, buf, size);
+ if (err)
+ goto out;
+ }
+
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
inarg.flags = flags;
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
inarg.flags = flags;
args.in.args[1].size = strlen(name) + 1;
args.in.args[1].value = name;
args.in.args[2].size = size;
args.in.args[1].size = strlen(name) + 1;
args.in.args[1].value = name;
args.in.args[2].size = size;
- args.in.args[2].value = value;
+ args.in.args[2].value = buf ? buf : value;
err = fuse_simple_request(fc, &args);
if (err == -ENOSYS) {
fc->no_setxattr = 1;
err = fuse_simple_request(fc, &args);
if (err == -ENOSYS) {
fc->no_setxattr = 1;
fuse_invalidate_attr(inode);
fuse_update_ctime(inode);
}
fuse_invalidate_attr(inode);
fuse_update_ctime(inode);
}
ret = fuse_simple_request(fc, &args);
if (!ret && !size)
ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
ret = fuse_simple_request(fc, &args);
if (!ret && !size)
ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
+ if (!ret) {
+ if (!size) {
+ ret = outarg.size;
+ } else if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
+ !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT)) {
+ ret = posix_acl_fix_xattr_userns(&init_user_ns,
+ inode->i_sb->s_user_ns,
+ value, size);
+ }
+ }
if (ret == -ENOSYS) {
fc->no_getxattr = 1;
ret = -EOPNOTSUPP;
if (ret == -ENOSYS) {
fc->no_getxattr = 1;
ret = -EOPNOTSUPP;