fs: introduce fsuidgid_has_mapping() helper

Don't open-code the checks and instead move them into a clean little
helper we can call. This also reduces the risk that if we ever change
something we forget to change all locations.

Link: https://lore.kernel.org/r/20210320122623.599086-4-christian.brauner@ubuntu.com
Inspired-by: Vivek Goyal <vgoyal@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2021-03-20 13:26:23 +01:00
Родитель a65e58e791
Коммит 8e5389132a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 91C61BC06578DCA2
2 изменённых файлов: 23 добавлений и 8 удалений

Просмотреть файл

@ -2823,16 +2823,14 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir,
static inline int may_create(struct user_namespace *mnt_userns, static inline int may_create(struct user_namespace *mnt_userns,
struct inode *dir, struct dentry *child) struct inode *dir, struct dentry *child)
{ {
struct user_namespace *s_user_ns;
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
if (child->d_inode) if (child->d_inode)
return -EEXIST; return -EEXIST;
if (IS_DEADDIR(dir)) if (IS_DEADDIR(dir))
return -ENOENT; return -ENOENT;
s_user_ns = dir->i_sb->s_user_ns; if (!fsuidgid_has_mapping(dir->i_sb, mnt_userns))
if (!kuid_has_mapping(s_user_ns, mapped_fsuid(mnt_userns)) ||
!kgid_has_mapping(s_user_ns, mapped_fsgid(mnt_userns)))
return -EOVERFLOW; return -EOVERFLOW;
return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC); return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC);
} }
@ -3034,14 +3032,11 @@ static int may_o_create(struct user_namespace *mnt_userns,
const struct path *dir, struct dentry *dentry, const struct path *dir, struct dentry *dentry,
umode_t mode) umode_t mode)
{ {
struct user_namespace *s_user_ns;
int error = security_path_mknod(dir, dentry, mode, 0); int error = security_path_mknod(dir, dentry, mode, 0);
if (error) if (error)
return error; return error;
s_user_ns = dir->dentry->d_sb->s_user_ns; if (!fsuidgid_has_mapping(dir->dentry->d_sb, mnt_userns))
if (!kuid_has_mapping(s_user_ns, mapped_fsuid(mnt_userns)) ||
!kgid_has_mapping(s_user_ns, mapped_fsgid(mnt_userns)))
return -EOVERFLOW; return -EOVERFLOW;
error = inode_permission(mnt_userns, dir->dentry->d_inode, error = inode_permission(mnt_userns, dir->dentry->d_inode,

Просмотреть файл

@ -1692,6 +1692,26 @@ static inline kgid_t mapped_fsgid(struct user_namespace *mnt_userns)
return kgid_from_mnt(mnt_userns, current_fsgid()); return kgid_from_mnt(mnt_userns, current_fsgid());
} }
/**
* fsuidgid_has_mapping() - check whether caller's fsuid/fsgid is mapped
* @sb: the superblock we want a mapping in
* @mnt_userns: user namespace of the relevant mount
*
* Check whether the caller's fsuid and fsgid have a valid mapping in the
* s_user_ns of the superblock @sb. If the caller is on an idmapped mount map
* the caller's fsuid and fsgid according to the @mnt_userns first.
*
* Return: true if fsuid and fsgid is mapped, false if not.
*/
static inline bool fsuidgid_has_mapping(struct super_block *sb,
struct user_namespace *mnt_userns)
{
struct user_namespace *s_user_ns = sb->s_user_ns;
return kuid_has_mapping(s_user_ns, mapped_fsuid(mnt_userns)) &&
kgid_has_mapping(s_user_ns, mapped_fsgid(mnt_userns));
}
extern struct timespec64 current_time(struct inode *inode); extern struct timespec64 current_time(struct inode *inode);
/* /*