Loading fs/coredump.c +2 −2 Original line number Diff line number Diff line Loading @@ -716,7 +716,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) * filesystem. */ 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())) { pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n", cn.corename); Loading fs/exec.c +8 −8 Original line number Diff line number Diff line Loading @@ -1591,8 +1591,8 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) struct user_namespace *mnt_userns; struct inode *inode = file_inode(file); unsigned int mode; kuid_t uid; kgid_t gid; vfsuid_t vfsuid; vfsgid_t vfsgid; if (!mnt_may_suid(file->f_path.mnt)) return; Loading @@ -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 */ mode = inode->i_mode; uid = i_uid_into_mnt(mnt_userns, inode); gid = i_gid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode); vfsgid = i_gid_into_vfsgid(mnt_userns, inode); inode_unlock(inode); /* We ignore suid/sgid if there are no mappings for them in the ns */ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || !kgid_has_mapping(bprm->cred->user_ns, gid)) if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) return; if (mode & S_ISUID) { 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)) { bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->cred->egid = gid; bprm->cred->egid = vfsgid_into_kgid(vfsgid); } } Loading fs/fuse/acl.c +1 −1 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry, return ret; } if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) && if (!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) && !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID)) extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID; Loading fs/inode.c +4 −4 Original line number Diff line number Diff line Loading @@ -2326,15 +2326,15 @@ EXPORT_SYMBOL(inode_init_owner); bool inode_owner_or_capable(struct user_namespace *mnt_userns, const struct inode *inode) { kuid_t i_uid; vfsuid_t vfsuid; struct user_namespace *ns; i_uid = i_uid_into_mnt(mnt_userns, inode); if (uid_eq(current_fsuid(), i_uid)) vfsuid = i_uid_into_vfsuid(mnt_userns, inode); if (vfsuid_eq_kuid(vfsuid, current_fsuid())) return true; 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 false; } Loading fs/namei.c +20 −20 Original line number Diff line number Diff line Loading @@ -336,11 +336,11 @@ static int acl_permission_check(struct user_namespace *mnt_userns, struct inode *inode, int mask) { unsigned int mode = inode->i_mode; kuid_t i_uid; vfsuid_t vfsuid; /* Are we the owner? If so, ACL's don't matter */ i_uid = i_uid_into_mnt(mnt_userns, inode); if (likely(uid_eq(current_fsuid(), i_uid))) { vfsuid = i_uid_into_vfsuid(mnt_userns, inode); if (likely(vfsuid_eq_kuid(vfsuid, current_fsuid()))) { mask &= 7; mode >>= 6; return (mask & ~mode) ? -EACCES : 0; Loading @@ -362,8 +362,8 @@ static int acl_permission_check(struct user_namespace *mnt_userns, * about? Need to check group ownership if so. */ if (mask & (mode ^ (mode >> 3))) { kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); if (in_group_p(kgid)) vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode); if (vfsgid_in_group_p(vfsgid)) mode >>= 3; } Loading Loading @@ -581,7 +581,7 @@ struct nameidata { struct nameidata *saved; unsigned root_seq; int dfd; kuid_t dir_uid; vfsuid_t dir_vfsuid; umode_t dir_mode; } __randomize_layout; Loading Loading @@ -1095,15 +1095,15 @@ fs_initcall(init_fs_namei_sysctls); static inline int may_follow_link(struct nameidata *nd, const struct inode *inode) { struct user_namespace *mnt_userns; kuid_t i_uid; vfsuid_t vfsuid; if (!sysctl_protected_symlinks) return 0; 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. */ if (uid_eq(current_cred()->fsuid, i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid())) return 0; /* Allowed if parent directory not sticky and world-writable. */ Loading @@ -1111,7 +1111,7 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod return 0; /* 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; if (nd->flags & LOOKUP_RCU) Loading Loading @@ -1183,8 +1183,8 @@ int may_linkat(struct user_namespace *mnt_userns, const struct path *link) struct inode *inode = link->dentry->d_inode; /* Inode writeback is not safe when the uid or gid are invalid. */ if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || !gid_valid(i_gid_into_mnt(mnt_userns, inode))) if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) || !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode))) return -EOVERFLOW; if (!sysctl_protected_hardlinks) Loading Loading @@ -1232,13 +1232,13 @@ static int may_create_in_sticky(struct user_namespace *mnt_userns, struct nameidata *nd, struct inode *const inode) { 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)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || likely(!(dir_mode & S_ISVTX)) || uid_eq(i_uid_into_mnt(mnt_userns, inode), dir_uid) || uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) vfsuid_eq(i_uid_into_vfsuid(mnt_userns, inode), dir_vfsuid) || vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid())) return 0; if (likely(dir_mode & 0002) || Loading Loading @@ -2307,7 +2307,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) OK: /* pathname or trailing symlink, done */ 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->flags &= ~LOOKUP_PARENT; return 0; Loading Loading @@ -2885,9 +2885,9 @@ int __check_sticky(struct user_namespace *mnt_userns, struct inode *dir, { 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; 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 !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER); } Loading Loading @@ -2926,8 +2926,8 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir, BUG_ON(victim->d_parent->d_inode != dir); /* Inode writeback is not safe when the uid or gid are invalid. */ if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || !gid_valid(i_gid_into_mnt(mnt_userns, inode))) if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) || !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode))) return -EOVERFLOW; audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); Loading Loading
fs/coredump.c +2 −2 Original line number Diff line number Diff line Loading @@ -716,7 +716,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) * filesystem. */ 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())) { pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n", cn.corename); Loading
fs/exec.c +8 −8 Original line number Diff line number Diff line Loading @@ -1591,8 +1591,8 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) struct user_namespace *mnt_userns; struct inode *inode = file_inode(file); unsigned int mode; kuid_t uid; kgid_t gid; vfsuid_t vfsuid; vfsgid_t vfsgid; if (!mnt_may_suid(file->f_path.mnt)) return; Loading @@ -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 */ mode = inode->i_mode; uid = i_uid_into_mnt(mnt_userns, inode); gid = i_gid_into_mnt(mnt_userns, inode); vfsuid = i_uid_into_vfsuid(mnt_userns, inode); vfsgid = i_gid_into_vfsgid(mnt_userns, inode); inode_unlock(inode); /* We ignore suid/sgid if there are no mappings for them in the ns */ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || !kgid_has_mapping(bprm->cred->user_ns, gid)) if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) || !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) return; if (mode & S_ISUID) { 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)) { bprm->per_clear |= PER_CLEAR_ON_SETID; bprm->cred->egid = gid; bprm->cred->egid = vfsgid_into_kgid(vfsgid); } } Loading
fs/fuse/acl.c +1 −1 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry, return ret; } if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) && if (!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) && !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID)) extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID; Loading
fs/inode.c +4 −4 Original line number Diff line number Diff line Loading @@ -2326,15 +2326,15 @@ EXPORT_SYMBOL(inode_init_owner); bool inode_owner_or_capable(struct user_namespace *mnt_userns, const struct inode *inode) { kuid_t i_uid; vfsuid_t vfsuid; struct user_namespace *ns; i_uid = i_uid_into_mnt(mnt_userns, inode); if (uid_eq(current_fsuid(), i_uid)) vfsuid = i_uid_into_vfsuid(mnt_userns, inode); if (vfsuid_eq_kuid(vfsuid, current_fsuid())) return true; 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 false; } Loading
fs/namei.c +20 −20 Original line number Diff line number Diff line Loading @@ -336,11 +336,11 @@ static int acl_permission_check(struct user_namespace *mnt_userns, struct inode *inode, int mask) { unsigned int mode = inode->i_mode; kuid_t i_uid; vfsuid_t vfsuid; /* Are we the owner? If so, ACL's don't matter */ i_uid = i_uid_into_mnt(mnt_userns, inode); if (likely(uid_eq(current_fsuid(), i_uid))) { vfsuid = i_uid_into_vfsuid(mnt_userns, inode); if (likely(vfsuid_eq_kuid(vfsuid, current_fsuid()))) { mask &= 7; mode >>= 6; return (mask & ~mode) ? -EACCES : 0; Loading @@ -362,8 +362,8 @@ static int acl_permission_check(struct user_namespace *mnt_userns, * about? Need to check group ownership if so. */ if (mask & (mode ^ (mode >> 3))) { kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); if (in_group_p(kgid)) vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode); if (vfsgid_in_group_p(vfsgid)) mode >>= 3; } Loading Loading @@ -581,7 +581,7 @@ struct nameidata { struct nameidata *saved; unsigned root_seq; int dfd; kuid_t dir_uid; vfsuid_t dir_vfsuid; umode_t dir_mode; } __randomize_layout; Loading Loading @@ -1095,15 +1095,15 @@ fs_initcall(init_fs_namei_sysctls); static inline int may_follow_link(struct nameidata *nd, const struct inode *inode) { struct user_namespace *mnt_userns; kuid_t i_uid; vfsuid_t vfsuid; if (!sysctl_protected_symlinks) return 0; 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. */ if (uid_eq(current_cred()->fsuid, i_uid)) if (vfsuid_eq_kuid(vfsuid, current_fsuid())) return 0; /* Allowed if parent directory not sticky and world-writable. */ Loading @@ -1111,7 +1111,7 @@ static inline int may_follow_link(struct nameidata *nd, const struct inode *inod return 0; /* 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; if (nd->flags & LOOKUP_RCU) Loading Loading @@ -1183,8 +1183,8 @@ int may_linkat(struct user_namespace *mnt_userns, const struct path *link) struct inode *inode = link->dentry->d_inode; /* Inode writeback is not safe when the uid or gid are invalid. */ if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || !gid_valid(i_gid_into_mnt(mnt_userns, inode))) if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) || !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode))) return -EOVERFLOW; if (!sysctl_protected_hardlinks) Loading Loading @@ -1232,13 +1232,13 @@ static int may_create_in_sticky(struct user_namespace *mnt_userns, struct nameidata *nd, struct inode *const inode) { 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)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || likely(!(dir_mode & S_ISVTX)) || uid_eq(i_uid_into_mnt(mnt_userns, inode), dir_uid) || uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) vfsuid_eq(i_uid_into_vfsuid(mnt_userns, inode), dir_vfsuid) || vfsuid_eq_kuid(i_uid_into_vfsuid(mnt_userns, inode), current_fsuid())) return 0; if (likely(dir_mode & 0002) || Loading Loading @@ -2307,7 +2307,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) OK: /* pathname or trailing symlink, done */ 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->flags &= ~LOOKUP_PARENT; return 0; Loading Loading @@ -2885,9 +2885,9 @@ int __check_sticky(struct user_namespace *mnt_userns, struct inode *dir, { 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; 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 !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FOWNER); } Loading Loading @@ -2926,8 +2926,8 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir, BUG_ON(victim->d_parent->d_inode != dir); /* Inode writeback is not safe when the uid or gid are invalid. */ if (!uid_valid(i_uid_into_mnt(mnt_userns, inode)) || !gid_valid(i_gid_into_mnt(mnt_userns, inode))) if (!vfsuid_valid(i_uid_into_vfsuid(mnt_userns, inode)) || !vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode))) return -EOVERFLOW; audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); Loading