]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: (namespace) fuse: Translate ids in posix acl xattrs
authorSeth Forshee <seth.forshee@canonical.com>
Wed, 24 Aug 2016 16:47:05 +0000 (11:47 -0500)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 20 Feb 2017 03:57:58 +0000 (20:57 -0700)
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>
fs/fuse/xattr.c

index 3caac46b08b0eeaad1493024d7102c81c2f41661..5126301751042e9e8dd623d52b6aa76470b3ce32 100644 (file)
@@ -16,12 +16,24 @@ int fuse_setxattr(struct inode *inode, const char *name, const void *value,
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
+       void *buf = NULL;
        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;
@@ -33,7 +45,7 @@ int fuse_setxattr(struct inode *inode, const char *name, const void *value,
        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;
@@ -43,6 +55,9 @@ int fuse_setxattr(struct inode *inode, const char *name, const void *value,
                fuse_invalidate_attr(inode);
                fuse_update_ctime(inode);
        }
+
+out:
+       kfree(buf);
        return err;
 }
 
@@ -80,6 +95,16 @@ ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
        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;