Commit e1212e9b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fs.vfsuid.conversion.v6.2' of...

Merge tag 'fs.vfsuid.conversion.v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping

Pull vfsuid updates from Christian Brauner:
 "Last cycle we introduced the vfs{g,u}id_t types and associated helpers
  to gain type safety when dealing with idmapped mounts. That initial
  work already converted a lot of places over but there were still some
  left,

  This converts all remaining places that still make use of non-type
  safe idmapping helpers to rely on the new type safe vfs{g,u}id based
  helpers.

  Afterwards it removes all the old non-type safe helpers"

* tag 'fs.vfsuid.conversion.v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping:
  fs: remove unused idmapping helpers
  ovl: port to vfs{g,u}id_t and associated helpers
  fuse: port to vfs{g,u}id_t and associated helpers
  ima: use type safe idmapping helpers
  apparmor: use type safe idmapping helpers
  caps: use type safe idmapping helpers
  fs: use type safe idmapping helpers
  mnt_idmapping: add missing helpers
parents cf619f89 eb7718cd
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -720,7 +720,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);
+8 −8
Original line number Diff line number Diff line
@@ -1599,8 +1599,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;
@@ -1619,23 +1619,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);
	}
}

+1 −1
Original line number Diff line number Diff line
@@ -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;

+4 −4
Original line number Diff line number Diff line
@@ -2323,15 +2323,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;
}
+20 −20
Original line number Diff line number Diff line
@@ -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;
@@ -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;
	}

@@ -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;

@@ -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. */
@@ -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)
@@ -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)
@@ -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) ||
@@ -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;
@@ -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);
}
@@ -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