summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAlexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>2024-09-03 17:16:15 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2024-09-04 16:48:22 +0200
commitd561254fb7ba451f580becb21ab3472bc0265080 (patch)
tree79481763d80e9da0b27e2f1854fc5f92ab5ce6fb /fs
parent10dc721836c0c968990a519e147d4cb7decdae5c (diff)
downloadlinux-stable-d561254fb7ba451f580becb21ab3472bc0265080.tar.gz
linux-stable-d561254fb7ba451f580becb21ab3472bc0265080.tar.bz2
linux-stable-d561254fb7ba451f580becb21ab3472bc0265080.zip
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dir.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 6ce7968365e7..8a936dc0072b 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -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;
}