From: Seth Forshee Date: Wed, 24 Aug 2016 16:47:05 +0000 (-0500) Subject: UBUNTU: SAUCE: (namespace) fuse: Translate ids in posix acl xattrs X-Git-Tag: Ubuntu-4.10.0-9.11~207 X-Git-Url: https://git.proxmox.com/?p=mirror_ubuntu-zesty-kernel.git;a=commitdiff_plain;h=564a1c442623aa574a0a5e7e639a92b53b2865c3 UBUNTU: SAUCE: (namespace) fuse: Translate ids in posix acl xattrs 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 --- diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c index 3caac46b08b0..512630175104 100644 --- a/fs/fuse/xattr.c +++ b/fs/fuse/xattr.c @@ -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;