]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: support idmapped FUSE_EXT_GROUPS
authorAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Tue, 3 Sep 2024 15:16:15 +0000 (17:16 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Wed, 4 Sep 2024 14:48:22 +0000 (16:48 +0200)
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>
fs/fuse/dir.c

index 6ce7968365e717c6fc9d39641fe8b0c67385569e..8a936dc0072bfa570873cd0bd884b5745356743e 100644 (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;
        }