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: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Alexander Mikhalitsyn 2024-09-03 17:16:15 +02:00 committed by Miklos Szeredi
parent 10dc721836
commit d561254fb7

View File

@ -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.
*/
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_ext_header *xh;
struct fuse_supp_groups *sg;
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);
u32 sg_len = fuse_ext_size(sizeof(*sg) + sizeof(sg->groups[0]));
if (parent_gid == (gid_t) -1 || gid_eq(kgid, current_fsgid()) ||
!in_group_p(kgid))
if (parent_gid == (gid_t) -1 || vfsgid_eq_kgid(vfsgid, current_fsgid()) ||
!vfsgid_in_group_p(vfsgid))
return 0;
xh = extend_arg(ext, sg_len);
@ -572,7 +576,8 @@ static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext)
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,
umode_t mode)
{
@ -583,7 +588,7 @@ static int get_create_ext(struct fuse_args *args,
if (fc->init_security)
err = get_security_context(dentry, mode, &ext);
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) {
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,
args.out_args[1].size = sizeof(*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)
goto out_free_ff;
@ -798,7 +803,7 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
args->out_args[0].value = &outarg;
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)
goto out_put_forget_req;
}