Commit d561254f authored by Alexander Mikhalitsyn's avatar Alexander Mikhalitsyn Committed by Miklos Szeredi

fuse: support idmapped FUSE_EXT_GROUPS

We don't need to remap parent_gid, but have to adjust
group membership checks and take idmapping into account.
Signed-off-by: default avatarAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 10dc7218
...@@ -545,17 +545,21 @@ static u32 fuse_ext_size(size_t size) ...@@ -545,17 +545,21 @@ static u32 fuse_ext_size(size_t size)
/* /*
* This adds just a single supplementary group that matches the parent's group. * This adds just a single supplementary group that matches the parent's group.
*/ */
static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext) static int get_create_supp_group(struct mnt_idmap *idmap,
struct inode *dir,
struct fuse_in_arg *ext)
{ {
struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_ext_header *xh; struct fuse_ext_header *xh;
struct fuse_supp_groups *sg; struct fuse_supp_groups *sg;
kgid_t kgid = dir->i_gid; kgid_t kgid = dir->i_gid;
vfsgid_t vfsgid = make_vfsgid(idmap, fc->user_ns, kgid);
gid_t parent_gid = from_kgid(fc->user_ns, kgid); gid_t parent_gid = from_kgid(fc->user_ns, kgid);
u32 sg_len = fuse_ext_size(sizeof(*sg) + sizeof(sg->groups[0])); u32 sg_len = fuse_ext_size(sizeof(*sg) + sizeof(sg->groups[0]));
if (parent_gid == (gid_t) -1 || gid_eq(kgid, current_fsgid()) || if (parent_gid == (gid_t) -1 || vfsgid_eq_kgid(vfsgid, current_fsgid()) ||
!in_group_p(kgid)) !vfsgid_in_group_p(vfsgid))
return 0; return 0;
xh = extend_arg(ext, sg_len); xh = extend_arg(ext, sg_len);
...@@ -572,7 +576,8 @@ static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext) ...@@ -572,7 +576,8 @@ static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext)
return 0; return 0;
} }
static int get_create_ext(struct fuse_args *args, static int get_create_ext(struct mnt_idmap *idmap,
struct fuse_args *args,
struct inode *dir, struct dentry *dentry, struct inode *dir, struct dentry *dentry,
umode_t mode) umode_t mode)
{ {
...@@ -583,7 +588,7 @@ static int get_create_ext(struct fuse_args *args, ...@@ -583,7 +588,7 @@ static int get_create_ext(struct fuse_args *args,
if (fc->init_security) if (fc->init_security)
err = get_security_context(dentry, mode, &ext); err = get_security_context(dentry, mode, &ext);
if (!err && fc->create_supp_group) if (!err && fc->create_supp_group)
err = get_create_supp_group(dir, &ext); err = get_create_supp_group(idmap, dir, &ext);
if (!err && ext.size) { if (!err && ext.size) {
WARN_ON(args->in_numargs >= ARRAY_SIZE(args->in_args)); WARN_ON(args->in_numargs >= ARRAY_SIZE(args->in_args));
...@@ -668,7 +673,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, ...@@ -668,7 +673,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
args.out_args[1].size = sizeof(*outopenp); args.out_args[1].size = sizeof(*outopenp);
args.out_args[1].value = outopenp; args.out_args[1].value = outopenp;
err = get_create_ext(&args, dir, entry, mode); err = get_create_ext(&nop_mnt_idmap, &args, dir, entry, mode);
if (err) if (err)
goto out_free_ff; goto out_free_ff;
...@@ -798,7 +803,7 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args, ...@@ -798,7 +803,7 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
args->out_args[0].value = &outarg; args->out_args[0].value = &outarg;
if (args->opcode != FUSE_LINK) { if (args->opcode != FUSE_LINK) {
err = get_create_ext(args, dir, entry, mode); err = get_create_ext(&nop_mnt_idmap, args, dir, entry, mode);
if (err) if (err)
goto out_put_forget_req; goto out_put_forget_req;
} }
......
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