Several places ask whether a filesystem can hold a given id. Each of them calls kuid_has_mapping() or kgid_has_mapping() on the user namespace of the filesystem: - fsuidgid_has_mapping(), when a file is created - posix_acl_valid(), for an ACL entry - the uid and gid mount options of tmpfs, fuse and bpffs - ovl_copy_up_one(), which runs with the credentials of the mounter, so current_user_ns() there is the user namespace of the overlay The same two helpers are also used for many unrelated questions. Nothing distinguishes the callers that ask about a filesystem, so there is no place for a rule that should apply to filesystems only. Add kuid_has_fsmapping() and kgid_has_fsmapping(), next to vfsuid_has_fsmapping() and vfsgid_has_fsmapping(), and use them in the places listed above. No functional change. Signed-off-by: Josef Bacik --- fs/fuse/inode.c | 4 ++-- fs/overlayfs/copy_up.c | 4 ++-- fs/posix_acl.c | 4 ++-- include/linux/fs.h | 4 ++-- include/linux/mnt_idmapping.h | 31 +++++++++++++++++++++++++++++++ kernel/bpf/inode.c | 4 ++-- mm/shmem.c | 4 ++-- 7 files changed, 43 insertions(+), 12 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1341b681d0ed..37712fce905b 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -888,7 +888,7 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param) * The requested uid must be representable in the * filesystem's idmapping. */ - if (!kuid_has_mapping(fsc->user_ns, kuid)) + if (!kuid_has_fsmapping(fsc->user_ns, kuid)) return invalfc(fsc, "Invalid user_id"); ctx->user_id = kuid; ctx->user_id_present = true; @@ -900,7 +900,7 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param) * The requested gid must be representable in the * filesystem's idmapping. */ - if (!kgid_has_mapping(fsc->user_ns, kgid)) + if (!kgid_has_fsmapping(fsc->user_ns, kgid)) return invalfc(fsc, "Invalid group_id"); ctx->group_id = kgid; ctx->group_id_present = true; diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index c147ad155b79..48cd09a2b69b 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -1173,8 +1173,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, if (err) return err; - if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) || - !kgid_has_mapping(current_user_ns(), ctx.stat.gid)) + if (!kuid_has_fsmapping(current_user_ns(), ctx.stat.uid) || + !kgid_has_fsmapping(current_user_ns(), ctx.stat.gid)) return -EOVERFLOW; /* diff --git a/fs/posix_acl.c b/fs/posix_acl.c index fe77934ea8f2..a2e2ca984d95 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -260,7 +260,7 @@ posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl) case ACL_USER: if (state != ACL_USER) return -EINVAL; - if (!kuid_has_mapping(user_ns, pa->e_uid)) + if (!kuid_has_fsmapping(user_ns, pa->e_uid)) return -EINVAL; needs_mask = 1; break; @@ -275,7 +275,7 @@ posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl) case ACL_GROUP: if (state != ACL_GROUP) return -EINVAL; - if (!kgid_has_mapping(user_ns, pa->e_gid)) + if (!kgid_has_fsmapping(user_ns, pa->e_gid)) return -EINVAL; needs_mask = 1; break; diff --git a/include/linux/fs.h b/include/linux/fs.h index 88748be03505..ea9b9d5a667d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1589,8 +1589,8 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb, kgid = mapped_fsgid(idmap, fs_userns); if (!gid_valid(kgid)) return false; - return kuid_has_mapping(fs_userns, kuid) && - kgid_has_mapping(fs_userns, kgid); + return kuid_has_fsmapping(fs_userns, kuid) && + kgid_has_fsmapping(fs_userns, kgid); } struct timespec64 current_time(struct inode *inode); diff --git a/include/linux/mnt_idmapping.h b/include/linux/mnt_idmapping.h index 78eeef4c2996..b5e0772aa190 100644 --- a/include/linux/mnt_idmapping.h +++ b/include/linux/mnt_idmapping.h @@ -136,6 +136,37 @@ kuid_t from_vfsuid(const struct mnt_idmap *idmap, kgid_t from_vfsgid(const struct mnt_idmap *idmap, struct user_namespace *fs_userns, vfsgid_t vfsgid); +/** + * kuid_has_fsmapping - check whether a filesystem can hold a kuid + * @fs_userns: the filesystem's idmapping + * @kuid: the kuid, after the idmapping of the mount has been applied + * + * Use this function, and not kuid_has_mapping(), for a kuid that is about to end + * up in a filesystem: as the owner of a file, in an ACL, by a mount option. + * + * Return: true if @kuid has a mapping in the filesystem, false if not. + */ +static inline bool kuid_has_fsmapping(struct user_namespace *fs_userns, + kuid_t kuid) +{ + return kuid_has_mapping(fs_userns, kuid); +} + +/** + * kgid_has_fsmapping - check whether a filesystem can hold a kgid + * @fs_userns: the filesystem's idmapping + * @kgid: the kgid, after the idmapping of the mount has been applied + * + * See kuid_has_fsmapping(). + * + * Return: true if @kgid has a mapping in the filesystem, false if not. + */ +static inline bool kgid_has_fsmapping(struct user_namespace *fs_userns, + kgid_t kgid) +{ + return kgid_has_mapping(fs_userns, kgid); +} + /** * vfsuid_has_fsmapping - check whether a vfsuid maps into the filesystem * @idmap: the mount's idmapping diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index c6f328e4752e..504bb7accb39 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -1026,7 +1026,7 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param) * The requested uid must be representable in the * filesystem's idmapping. */ - if (!kuid_has_mapping(fc->user_ns, uid)) + if (!kuid_has_fsmapping(fc->user_ns, uid)) goto bad_value; opts->uid = uid; @@ -1040,7 +1040,7 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param) * The requested gid must be representable in the * filesystem's idmapping. */ - if (!kgid_has_mapping(fc->user_ns, gid)) + if (!kgid_has_fsmapping(fc->user_ns, gid)) goto bad_value; opts->gid = gid; diff --git a/mm/shmem.c b/mm/shmem.c index af21a89abb0f..8e7b51797ab8 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -4793,7 +4793,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) * The requested uid must be representable in the * filesystem's idmapping. */ - if (!kuid_has_mapping(fc->user_ns, kuid)) + if (!kuid_has_fsmapping(fc->user_ns, kuid)) goto bad_value; ctx->uid = kuid; @@ -4805,7 +4805,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) * The requested gid must be representable in the * filesystem's idmapping. */ - if (!kgid_has_mapping(fc->user_ns, kgid)) + if (!kgid_has_fsmapping(fc->user_ns, kgid)) goto bad_value; ctx->gid = kgid; -- 2.55.0