fs: use type safe idmapping helpers

We already ported most parts and filesystems over for v6.0 to the new
vfs{g,u}id_t type and associated helpers for v6.0. Convert the remaining
places so we can remove all the old helpers.
This is a non-functional change.

Reviewed-by: Seth Forshee (DigitalOcean) <sforshee@kernel.org>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2022-06-22 22:12:16 +02:00 коммит произвёл Christian Brauner (Microsoft)
Родитель 9c4f28ddfb
Коммит a2bd096fb2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 91C61BC06578DCA2
6 изменённых файлов: 40 добавлений и 37 удалений

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

@ -716,8 +716,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
* filesystem. * filesystem.
*/ */
mnt_userns = file_mnt_user_ns(cprm.file); mnt_userns = file_mnt_user_ns(cprm.file);
if (!uid_eq(i_uid_into_mnt(mnt_userns, inode), if (!vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode),
current_fsuid())) { current_fsuid())) {
pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n", pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n",
cn.corename); cn.corename);
goto close_fail; goto close_fail;

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

@ -1591,8 +1591,8 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
struct user_namespace *mnt_userns; struct user_namespace *mnt_userns;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
unsigned int mode; unsigned int mode;
kuid_t uid; vfsuid_t vfsuid;
kgid_t gid; vfsgid_t vfsgid;
if (!mnt_may_suid(file->f_path.mnt)) if (!mnt_may_suid(file->f_path.mnt))
return; return;
@ -1611,23 +1611,23 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
/* reload atomically mode/uid/gid now that lock held */ /* reload atomically mode/uid/gid now that lock held */
mode = inode->i_mode; mode = inode->i_mode;
uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
gid = i_gid_into_mnt(mnt_userns, inode); vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
inode_unlock(inode); inode_unlock(inode);
/* We ignore suid/sgid if there are no mappings for them in the ns */ /* We ignore suid/sgid if there are no mappings for them in the ns */
if (!kuid_has_mapping(bprm->cred->user_ns, uid) || if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||
!kgid_has_mapping(bprm->cred->user_ns, gid)) !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid))
return; return;
if (mode & S_ISUID) { if (mode & S_ISUID) {
bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->euid = uid; bprm->cred->euid = vfsuid_into_kuid(vfsuid);
} }
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->egid = gid; bprm->cred->egid = vfsgid_into_kgid(vfsgid);
} }
} }

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

@ -2326,15 +2326,15 @@ EXPORT_SYMBOL(inode_init_owner);
bool inode_owner_or_capable(struct user_namespace *mnt_userns, bool inode_owner_or_capable(struct user_namespace *mnt_userns,
const struct inode *inode) const struct inode *inode)
{ {
kuid_t i_uid; vfsuid_t vfsuid;
struct user_namespace *ns; struct user_namespace *ns;
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
if (uid_eq(current_fsuid(), i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
return true; return true;
ns = current_user_ns(); ns = current_user_ns();
if (kuid_has_mapping(ns, i_uid) && ns_capable(ns, CAP_FOWNER)) if (vfsuid_has_mapping(ns, vfsuid) && ns_capable(ns, CAP_FOWNER))
return true; return true;
return false; return false;
} }

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

@ -336,11 +336,11 @@ static int acl_permission_check(struct user_namespace *mnt_userns,
struct inode *inode, int mask) struct inode *inode, int mask)
{ {
unsigned int mode = inode->i_mode; unsigned int mode = inode->i_mode;
kuid_t i_uid; vfsuid_t vfsuid;
/* Are we the owner? If so, ACL's don't matter */ /* Are we the owner? If so, ACL's don't matter */
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
if (likely(uid_eq(current_fsuid(), i_uid))) { if (likely(vfsuid_eq_kuid(vfsuid, current_fsuid()))) {
mask &= 7; mask &= 7;
mode >>= 6; mode >>= 6;
return (mask & ~mode) ? -EACCES : 0; return (mask & ~mode) ? -EACCES : 0;
@ -362,8 +362,8 @@ static int acl_permission_check(struct user_namespace *mnt_userns,
* about? Need to check group ownership if so. * about? Need to check group ownership if so.
*/ */
if (mask & (mode ^ (mode >> 3))) { if (mask & (mode ^ (mode >> 3))) {
kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
if (in_group_p(kgid)) if (vfsgid_in_group_p(vfsgid))
mode >>= 3; mode >>= 3;
} }
@ -581,7 +581,7 @@ struct nameidata {
struct nameidata *saved; struct nameidata *saved;
unsigned root_seq; unsigned root_seq;
int dfd; int dfd;
kuid_t dir_uid; vfsuid_t dir_vfsuid;
umode_t dir_mode; umode_t dir_mode;
} __randomize_layout; } __randomize_layout;
@ -1095,15 +1095,15 @@ fs_initcall(init_fs_namei_sysctls);
static inline int may_follow_link(struct nameidata *nd, const struct inode *inode) static inline int may_follow_link(struct nameidata *nd, const struct inode *inode)
{ {
struct user_namespace *mnt_userns; struct user_namespace *mnt_userns;
kuid_t i_uid; vfsuid_t vfsuid;
if (!sysctl_protected_symlinks) if (!sysctl_protected_symlinks)
return 0; return 0;
mnt_userns = mnt_user_ns(nd->path.mnt); mnt_userns = mnt_user_ns(nd->path.mnt);
i_uid = i_uid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
/* Allowed if owner and follower match. */ /* Allowed if owner and follower match. */
if (uid_eq(current_cred()->fsuid, i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
return 0; return 0;
/* Allowed if parent directory not sticky and world-writable. */ /* Allowed if parent directory not sticky and world-writable. */
@ -1111,7 +1111,7 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod
return 0; return 0;
/* Allowed if parent directory and link owner match. */ /* Allowed if parent directory and link owner match. */
if (uid_valid(nd->dir_uid) && uid_eq(nd->dir_uid, i_uid)) if (vfsuid_valid(nd->dir_vfsuid) && vfsuid_eq(nd->dir_vfsuid, vfsuid))
return 0; return 0;
if (nd->flags & LOOKUP_RCU) if (nd->flags & LOOKUP_RCU)
@ -1183,8 +1183,8 @@ int may_linkat(struct user_namespace *mnt_userns, const struct path *link)
struct inode *inode = link->dentry->d_inode; struct inode *inode = link->dentry->d_inode;
/* Inode writeback is not safe when the uid or gid are invalid. */ /* Inode writeback is not safe when the uid or gid are invalid. */
if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) ||
!gid_valid(i_gid_into_mnt(mnt_userns, inode))) !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
return -EOVERFLOW; return -EOVERFLOW;
if (!sysctl_protected_hardlinks) if (!sysctl_protected_hardlinks)
@ -1232,13 +1232,13 @@ static int may_create_in_sticky(struct user_namespace *mnt_userns,
struct nameidata *nd, struct inode *const inode) struct nameidata *nd, struct inode *const inode)
{ {
umode_t dir_mode = nd->dir_mode; umode_t dir_mode = nd->dir_mode;
kuid_t dir_uid = nd->dir_uid; vfsuid_t dir_vfsuid = nd->dir_vfsuid;
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
likely(!(dir_mode & S_ISVTX)) || likely(!(dir_mode & S_ISVTX)) ||
uid_eq(i_uid_into_mnt(mnt_userns, inode), dir_uid) || vfsuid_eq(i_uid_into_vfsuid(mnt_userns, inode), dir_vfsuid) ||
uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid()))
return 0; return 0;
if (likely(dir_mode & 0002) || if (likely(dir_mode & 0002) ||
@ -2307,7 +2307,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
OK: OK:
/* pathname or trailing symlink, done */ /* pathname or trailing symlink, done */
if (!depth) { if (!depth) {
nd->dir_uid = i_uid_into_mnt(mnt_userns, nd->inode); nd->dir_vfsuid = i_uid_into_vfsuid(mnt_userns, nd->inode);
nd->dir_mode = nd->inode->i_mode; nd->dir_mode = nd->inode->i_mode;
nd->flags &= ~LOOKUP_PARENT; nd->flags &= ~LOOKUP_PARENT;
return 0; return 0;
@ -2885,9 +2885,9 @@ int __check_sticky(struct user_namespace *mnt_userns, struct inode *dir,
{ {
kuid_t fsuid = current_fsuid(); kuid_t fsuid = current_fsuid();
if (uid_eq(i_uid_into_mnt(mnt_userns, inode), fsuid)) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), fsuid))
return 0; return 0;
if (uid_eq(i_uid_into_mnt(mnt_userns, dir), fsuid)) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, dir), fsuid))
return 0; return 0;
return !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER); return !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER);
} }
@ -2926,8 +2926,8 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir,
BUG_ON(victim->d_parent->d_inode != dir); BUG_ON(victim->d_parent->d_inode != dir);
/* Inode writeback is not safe when the uid or gid are invalid. */ /* Inode writeback is not safe when the uid or gid are invalid. */
if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) ||
!gid_valid(i_gid_into_mnt(mnt_userns, inode))) !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode)))
return -EOVERFLOW; return -EOVERFLOW;
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);

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

@ -429,7 +429,7 @@ static bool allow_file_dedupe(struct file *file)
return true; return true;
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITE)
return true; return true;
if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) if (vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid()))
return true; return true;
if (!inode_permission(mnt_userns, inode, MAY_WRITE)) if (!inode_permission(mnt_userns, inode, MAY_WRITE))
return true; return true;

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

@ -44,12 +44,15 @@
void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode, void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode,
struct kstat *stat) struct kstat *stat)
{ {
vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_userns, inode);
vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
stat->dev = inode->i_sb->s_dev; stat->dev = inode->i_sb->s_dev;
stat->ino = inode->i_ino; stat->ino = inode->i_ino;
stat->mode = inode->i_mode; stat->mode = inode->i_mode;
stat->nlink = inode->i_nlink; stat->nlink = inode->i_nlink;
stat->uid = i_uid_into_mnt(mnt_userns, inode); stat->uid = vfsuid_into_kuid(vfsuid);
stat->gid = i_gid_into_mnt(mnt_userns, inode); stat->gid = vfsgid_into_kgid(vfsgid);
stat->rdev = inode->i_rdev; stat->rdev = inode->i_rdev;
stat->size = i_size_read(inode); stat->size = i_size_read(inode);
stat->atime = inode->i_atime; stat->atime = inode->i_atime;