linux-raid.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serge@hallyn.com>
To: Seth Forshee <seth.forshee@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Serge Hallyn <serge.hallyn@canonical.com>,
	Richard Weinberger <richard.weinberger@gmail.com>,
	Austin S Hemmelgarn <ahferroin7@gmail.com>,
	Miklos Szeredi <mszeredi@redhat.com>,
	Pavel Tikhomirov <ptikhomirov@virtuozzo.com>,
	linux-kernel@vger.kernel.org, linux-bcache@vger.kernel.org,
	dm-devel@redhat.com, linux-raid@vger.kernel.org,
	linux-mtd@lists.infradead.org, linux-fsdevel@vger.kernel.org,
	fuse-devel@lists.sourceforge.net,
	linux-security-module@vger.kernel.org, selinux@tycho.nsa.gov,
	cgroups@vger.kernel.org
Subject: Re: [PATCH v3 14/21] fs: Allow superblock owner to change ownership of inodes with unmappable ids
Date: Mon, 25 Apr 2016 15:30:47 -0500	[thread overview]
Message-ID: <20160425203047.GA29927@mail.hallyn.com> (raw)
In-Reply-To: <1461339521-123191-15-git-send-email-seth.forshee@canonical.com>

Quoting Seth Forshee (seth.forshee@canonical.com):
> In a userns mount some on-disk inodes may have ids which do not
> map into s_user_ns, in which case the in-kernel inodes are owned
> by invalid users. The superblock owner should be able to change
> attributes of these inodes but cannot. However it is unsafe to
> grant the superblock owner privileged access to all inodes in the
> superblock since proc, sysfs, etc. use DAC to protect files which
> may not belong to s_user_ns. The problem is restricted to only
> inodes where the owner or group is an invalid user.
> 
> We can work around this by allowing users with CAP_CHOWN in
> s_user_ns to change an invalid owner or group id, so long as the
> other id is either invalid or mappable in s_user_ns. After
> changing ownership the user will be privileged towards the inode
> and thus able to change other attributes.
> 
> As an precaution, checks for invalid ids are added to the proc
> and kernfs setattr interfaces. These filesystems are not expected
> to have inodes with invalid ids, but if it does happen any
> setattr operations will return -EPERM.
> 
> Signed-off-by: Seth Forshee <seth.forshee@canonical.com>

Acked-by: Serge Hallyn <serge.hallyn@canonical.com>

bug a request below,

> ---
>  fs/attr.c             | 47 +++++++++++++++++++++++++++++++++++++++--------
>  fs/kernfs/inode.c     |  2 ++
>  fs/proc/base.c        |  2 ++
>  fs/proc/generic.c     |  3 +++
>  fs/proc/proc_sysctl.c |  2 ++
>  5 files changed, 48 insertions(+), 8 deletions(-)
> 
> diff --git a/fs/attr.c b/fs/attr.c
> index 3cfaaac4a18e..a8b0931654a5 100644
> --- a/fs/attr.c
> +++ b/fs/attr.c
> @@ -16,6 +16,43 @@
>  #include <linux/evm.h>
>  #include <linux/ima.h>
>  
> +static bool chown_ok(const struct inode *inode, kuid_t uid)
> +{
> +	struct user_namespace *user_ns;
> +
> +	if (uid_eq(current_fsuid(), inode->i_uid) && uid_eq(uid, inode->i_uid))
> +		return true;
> +	if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
> +		return true;
> +
> +	user_ns = inode->i_sb->s_user_ns;
> +	if (!uid_valid(inode->i_uid) &&
> +	    (!gid_valid(inode->i_gid) || kgid_has_mapping(user_ns, inode->i_gid)) &&

This confused me to no end :)  Perhaps a "is_unmapped_valid_gid()" helper
would make it clearer what this is meant to do?  Or else maybe a comment
above chown_ok(), explaining that

1. for a blockdev, the uid is converted at inode read so that it is
either mapped or invalid
2. for sysfs / etc, uid can be valid but not mapped into the userns

> +	    ns_capable(user_ns, CAP_CHOWN))
> +		return true;
> +
> +	return false;
> +}
> +
> +static bool chgrp_ok(const struct inode *inode, kgid_t gid)
> +{
> +	struct user_namespace *user_ns;
> +
> +	if (uid_eq(current_fsuid(), inode->i_uid) &&
> +	    (in_group_p(gid) || gid_eq(gid, inode->i_gid)))
> +		return true;
> +	if (capable_wrt_inode_uidgid(inode, CAP_CHOWN))
> +		return true;
> +
> +	user_ns = inode->i_sb->s_user_ns;
> +	if (!gid_valid(inode->i_gid) &&
> +	    (!uid_valid(inode->i_uid) || kuid_has_mapping(user_ns, inode->i_uid)) &&
> +	    ns_capable(user_ns, CAP_CHOWN))
> +		return true;
> +
> +	return false;
> +}
> +
>  /**
>   * inode_change_ok - check if attribute changes to an inode are allowed
>   * @inode:	inode to check
> @@ -58,17 +95,11 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr)
>  		return 0;
>  
>  	/* Make sure a caller can chown. */
> -	if ((ia_valid & ATTR_UID) &&
> -	    (!uid_eq(current_fsuid(), inode->i_uid) ||
> -	     !uid_eq(attr->ia_uid, inode->i_uid)) &&
> -	    !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
> +	if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid))
>  		return -EPERM;
>  
>  	/* Make sure caller can chgrp. */
> -	if ((ia_valid & ATTR_GID) &&
> -	    (!uid_eq(current_fsuid(), inode->i_uid) ||
> -	    (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) &&
> -	    !capable_wrt_inode_uidgid(inode, CAP_CHOWN))
> +	if ((ia_valid & ATTR_GID) && !chgrp_ok(inode, attr->ia_gid))
>  		return -EPERM;
>  
>  	/* Make sure a caller can chmod. */
> diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
> index 16405ae88d2d..2e97a337ee5f 100644
> --- a/fs/kernfs/inode.c
> +++ b/fs/kernfs/inode.c
> @@ -117,6 +117,8 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
>  
>  	if (!kn)
>  		return -EINVAL;
> +	if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
> +		return -EPERM;
>  
>  	mutex_lock(&kernfs_mutex);
>  	error = inode_change_ok(inode, iattr);
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index b1755b23893e..648d623e2158 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -711,6 +711,8 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
>  
>  	if (attr->ia_valid & ATTR_MODE)
>  		return -EPERM;
> +	if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
> +		return -EPERM;
>  
>  	error = inode_change_ok(inode, attr);
>  	if (error)
> diff --git a/fs/proc/generic.c b/fs/proc/generic.c
> index ff3ffc76a937..1461570c552c 100644
> --- a/fs/proc/generic.c
> +++ b/fs/proc/generic.c
> @@ -105,6 +105,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
>  	struct proc_dir_entry *de = PDE(inode);
>  	int error;
>  
> +	if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
> +		return -EPERM;
> +
>  	error = inode_change_ok(inode, iattr);
>  	if (error)
>  		return error;
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index fe5b6e6c4671..f5d575157194 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -752,6 +752,8 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
>  
>  	if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
>  		return -EPERM;
> +	if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid))
> +		return -EPERM;
>  
>  	error = inode_change_ok(inode, attr);
>  	if (error)
> -- 
> 1.9.1

  reply	other threads:[~2016-04-25 20:30 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-22 15:38 [PATCH v3 00/21] Support fuse mounts in user namespaces Seth Forshee
2016-04-22 15:38 ` [PATCH v3 01/21] fs: fix a posible leak of allocated superblock Seth Forshee
2016-04-22 15:38 ` [PATCH v3 04/21] block_dev: Support checking inode permissions in lookup_bdev() Seth Forshee
2016-04-22 15:38 ` [PATCH v3 13/21] fs: Update posix_acl support to handle user namespace mounts Seth Forshee
     [not found] ` <1461339521-123191-1-git-send-email-seth.forshee-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
2016-04-22 15:38   ` [PATCH v3 02/21] fs: Remove check of s_user_ns for existing mounts in fs_fully_visible() Seth Forshee
2016-04-22 15:38   ` [PATCH v3 03/21] fs: Allow sysfs and cgroupfs to share super blocks between user namespaces Seth Forshee
2016-04-25 19:01     ` Serge E. Hallyn
2016-04-22 15:38   ` [PATCH v3 05/21] block_dev: Check permissions towards block device inode when mounting Seth Forshee
2016-04-22 15:38   ` [PATCH v3 06/21] fs: Treat foreign mounts as nosuid Seth Forshee
2016-04-22 15:38   ` [PATCH v3 07/21] selinux: Add support for unprivileged mounts from user namespaces Seth Forshee
2016-04-22 15:38   ` [PATCH v3 08/21] userns: Replace in_userns with current_in_userns Seth Forshee
2016-04-22 15:38   ` [PATCH v3 09/21] Smack: Handle labels consistently in untrusted mounts Seth Forshee
2016-04-22 15:38   ` [PATCH v3 10/21] fs: Check for invalid i_uid in may_follow_link() Seth Forshee
2016-04-22 15:38   ` [PATCH v3 11/21] cred: Reject inodes with invalid ids in set_create_file_as() Seth Forshee
2016-04-22 15:38   ` [PATCH v3 12/21] fs: Refuse uid/gid changes which don't map into s_user_ns Seth Forshee
2016-04-22 15:38   ` [PATCH v3 14/21] fs: Allow superblock owner to change ownership of inodes with unmappable ids Seth Forshee
2016-04-25 20:30     ` Serge E. Hallyn [this message]
2016-04-25 20:54       ` Seth Forshee
2016-04-22 15:38   ` [PATCH v3 15/21] fs: Don't remove suid for CAP_FSETID in s_user_ns Seth Forshee
2016-04-22 15:38   ` [PATCH v3 16/21] fs: Allow superblock owner to access do_remount_sb() Seth Forshee
2016-04-22 15:38   ` [PATCH v3 17/21] capabilities: Allow privileged user in s_user_ns to set security.* xattrs Seth Forshee
2016-04-22 15:38   ` [PATCH v3 18/21] fuse: Add support for pid namespaces Seth Forshee
2016-04-22 15:38   ` [PATCH v3 19/21] fuse: Support fuse filesystems outside of init_user_ns Seth Forshee
2016-04-22 15:38   ` [PATCH v3 20/21] fuse: Restrict allow_other to the superblock's namespace or a descendant Seth Forshee
2016-04-22 15:38 ` [PATCH v3 21/21] fuse: Allow user namespace mounts Seth Forshee

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160425203047.GA29927@mail.hallyn.com \
    --to=serge@hallyn.com \
    --cc=ahferroin7@gmail.com \
    --cc=cgroups@vger.kernel.org \
    --cc=dm-devel@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=fuse-devel@lists.sourceforge.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-bcache@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mszeredi@redhat.com \
    --cc=ptikhomirov@virtuozzo.com \
    --cc=richard.weinberger@gmail.com \
    --cc=selinux@tycho.nsa.gov \
    --cc=serge.hallyn@canonical.com \
    --cc=seth.forshee@canonical.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).