Commit 2036ce60 authored by Seth Forshee's avatar Seth Forshee Committed by Luis Henriques

UBUNTU: SAUCE: (namespace) fuse: Translate ids in posix acl xattrs

BugLink: http://bugs.launchpad.net/bugs/1634964

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: default avatarSeth Forshee <seth.forshee@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 5a10b5bd
......@@ -13,6 +13,8 @@
#include <linux/sched.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <uapi/linux/xattr.h>
#include <linux/posix_acl_xattr.h>
static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
{
......@@ -1757,12 +1759,24 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
struct inode *inode = d_inode(entry);
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;
......@@ -1774,7 +1788,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
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;
......@@ -1784,6 +1798,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
fuse_invalidate_attr(inode);
fuse_update_ctime(inode);
}
out:
kfree(buf);
return err;
}
......@@ -1820,8 +1836,16 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
args.out.args[0].value = &outarg;
}
ret = fuse_simple_request(fc, &args);
if (!ret && !size)
ret = outarg.size;
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment