diff options
author | Christian Brauner <brauner@kernel.org> | 2022-10-17 18:06:34 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-03-03 13:52:24 +0300 |
commit | 18c2750856dc907ccff05c747e079495f75ea35c (patch) | |
tree | 237e771ee2830d84b5d814332f0ac68f821c822d /fs/inode.c | |
parent | 118ad80d27d938868299ef184f7483b21f011f0b (diff) | |
download | linux-18c2750856dc907ccff05c747e079495f75ea35c.tar.xz |
attr: add in_group_or_capable()
commit 11c2a8700cdcabf9b639b7204a1e38e2a0b6798e upstream.
In setattr_{copy,prepare}() we need to perform the same permission
checks to determine whether we need to drop the setgid bit or not.
Instead of open-coding it twice add a simple helper the encapsulates the
logic. We will reuse this helpers to make dropping the setgid bit during
write operations more consistent in a follow up patch.
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/inode.c b/fs/inode.c index b608528efd3a..55299b710c45 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2488,6 +2488,28 @@ struct timespec64 current_time(struct inode *inode) EXPORT_SYMBOL(current_time); /** + * in_group_or_capable - check whether caller is CAP_FSETID privileged + * @mnt_userns: user namespace of the mount @inode was found from + * @inode: inode to check + * @vfsgid: the new/current vfsgid of @inode + * + * Check wether @vfsgid is in the caller's group list or if the caller is + * privileged with CAP_FSETID over @inode. This can be used to determine + * whether the setgid bit can be kept or must be dropped. + * + * Return: true if the caller is sufficiently privileged, false if not. + */ +bool in_group_or_capable(struct user_namespace *mnt_userns, + const struct inode *inode, vfsgid_t vfsgid) +{ + if (vfsgid_in_group_p(vfsgid)) + return true; + if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID)) + return true; + return false; +} + +/** * mode_strip_sgid - handle the sgid bit for non-directories * @mnt_userns: User namespace of the mount the inode was created from * @dir: parent directory inode @@ -2508,11 +2530,9 @@ umode_t mode_strip_sgid(struct user_namespace *mnt_userns, return mode; if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID)) return mode; - if (in_group_p(i_gid_into_mnt(mnt_userns, dir))) - return mode; - if (capable_wrt_inode_uidgid(mnt_userns, dir, CAP_FSETID)) + if (in_group_or_capable(mnt_userns, dir, + i_gid_into_vfsgid(mnt_userns, dir))) return mode; - return mode & ~S_ISGID; } EXPORT_SYMBOL(mode_strip_sgid); |