linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Andrew Vagin <avagin@virtuozzo.com>
Cc: Andrey Vagin <avagin@openvz.org>, <linux-kernel@vger.kernel.org>,
	James Bottomley <James.Bottomley@HansenPartnership.com>,
	Serge Hallyn <serge.hallyn@canonical.com>,
	<linux-api@vger.kernel.org>,
	<containers@lists.linux-foundation.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>, <criu@openvz.org>,
	<linux-fsdevel@vger.kernel.org>,
	"Michael Kerrisk \(man-pages\)" <mtk.manpages@gmail.com>
Subject: Re: [PATCH 2/5] kernel: add a helper to get an owning user namespace for a namespace
Date: Sun, 24 Jul 2016 09:30:03 -0500	[thread overview]
Message-ID: <87shuzglck.fsf@x220.int.ebiederm.org> (raw)
In-Reply-To: <20160724063728.GA17810@outlook.office365.com> (Andrew Vagin's message of "Sat, 23 Jul 2016 23:37:29 -0700")

Andrew Vagin <avagin@virtuozzo.com> writes:

> On Sun, Jul 24, 2016 at 12:03:49AM -0500, Eric W. Biederman wrote:
>> Andrey Vagin <avagin@openvz.org> writes:
>> 
>> > Return -EPERM if an owning user namespace is outside of a process
>> > current user namespace.
>> >
>> > diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
>> > index a5bc78c..6382e5e 100644
>> > --- a/kernel/user_namespace.c
>> > +++ b/kernel/user_namespace.c
>> > @@ -994,6 +994,30 @@ static int userns_install(struct nsproxy *nsproxy, struct ns_common *ns)
>> >  	return commit_creds(cred);
>> >  }
>> >  
>> > +struct ns_common *ns_get_owner(struct ns_common *ns)
>> > +{
>> > +	const struct cred *cred = current_cred();
>> > +	struct user_namespace *user_ns, *p;
>> > +
>> > +	user_ns = p = ns->user_ns;
>> > +	if (user_ns == NULL) { /* ns is init_user_ns */
>> > +		/* Unprivileged user should not know that it's init_user_ns. */
>> > +		if (capable(CAP_SYS_ADMIN))
>> > +			return ERR_PTR(-ENOENT);
>> > +		return ERR_PTR(-EPERM);
>> > +	}
>> 
>> This permission check is not what I meant to request.  This does not
>> handle nested user namespaces.
>
> Here I handle a case when ns is init_user_ns. init_user_ns doesn't have
> a parent, so we need to return an error. We can't return ENOENT in all
> cases, because we don't want to expose "that file descriptor is for the
> root user namespace" to unprivileged users.
> (Trevor suggested to add this check and it looks resonable for me
> too).

Apologies. I was skimming and misread the code.  I mistook that loop for
some useful part of getting the owner.  Looking in more detail...

Your code says:
+struct ns_common *ns_get_owner(struct ns_common *ns)
+{
+	const struct cred *cred = current_cred();
+	struct user_namespace *user_ns, *p;
+
+	user_ns = p = ns->user_ns;
+	if (user_ns == NULL) { /* ns is init_user_ns */
+		/* Unprivileged user should not know that it's init_user_ns. */
+		if (capable(CAP_SYS_ADMIN))
+			return ERR_PTR(-ENOENT);
+		return ERR_PTR(-EPERM);
+	}
+
+	for (;;) {
+		if (p == cred->user_ns)
+			break;
+		if (p == &init_user_ns)
+			return ERR_PTR(-EPERM);
+		p = p->parent;
+	}
+
+	return &get_user_ns(user_ns)->ns;
+}

And all else being equal it could say:

+struct ns_common *ns_get_owner(struct ns_common *ns)
s+{
+	struct user_namespace *user_ns = ns->user_ns;
+
+	/* Are we allowed to see the user namespace? */
+	if (!ns_capable(user_ns?user_ns:&init_user_ns, CAP_SYS_ADMIN))
+		return ERR_PTR(-EPERM);
+
+	if (!user_ns)
+		return ERR_PTR(-ENOENT);
+
+	return &get_user_ns(user_ns)->ns;
+}

Which I think is the root of my confusion.  You hand rolled ns_capable,
and I did not recognize it because I was skimming, and just looking to
be certain the permission check was present.

Given that you have to hand roll the pid namespace check that hand
rolling may not be so bad.  But it certainly was confusing the first
time I saw it especially without a comment.

Hmm.

I am not at all certain it makes sense to return -ENOENT.

Without the -ENOENT check the code is much cleaner, and clearer.

I may be blinkered but I don't see the value in letting someone know we
are talking about the initial namespace.  If anything that information
is likely to cause issues with weird corner cases of checkpoint/restart,
as it acts different if you are in a container or not.

When things act different in a container that almost always is a source
of a problem somewhere.

So we could simplify the filter in the code to just this.

+struct ns_common *ns_get_owner(struct ns_common *ns)
+{
+	struct user_namespace *my_user_ns = current_user_ns();
+	struct user_namespace *owner, *p;
+
+	/* See if the owner is in the current user namespace */
+	owner = p = ns->user_ns;
+	for (;;) {
+		if (!p)
+			return ERR_PTR(-EPERM);
+		if (p == my_user_ns)
+			break;
+		p = p->parent;
+	}
+
+	return &get_user_ns(owner)->ns;
+}

And on reflection I do see the point of not using ns_capable as that
requires having privileges in a namespace while all we want here
is to see if someone is in a visible namespace.

So please ignore my comments about ns_capable on the pid namespace
parent.

But please simplify the loop and put an appropriate comment on it like I
have above.  The fewer special cases the easier the code is to get
correct, and the easier it is to read.

Eric

  reply	other threads:[~2016-07-24 14:43 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-14 18:20 [PATCH 0/5 RFC] Add an interface to discover relationships between namespaces Andrey Vagin
2016-07-14 18:20 ` [PATCH 1/5] namespaces: move user_ns into ns_common Andrey Vagin
2016-07-15 12:21   ` kbuild test robot
2016-07-14 18:20 ` [PATCH 2/5] kernel: add a helper to get an owning user namespace for a namespace Andrey Vagin
2016-07-14 19:07   ` W. Trevor King
2016-07-14 18:20 ` [PATCH 3/5] nsfs: add ioctl to get an owning user namespace for ns file descriptor Andrey Vagin
2016-07-14 18:48   ` W. Trevor King
2016-07-14 18:20 ` [PATCH 4/5] nsfs: add ioctl to get a parent namespace Andrey Vagin
2016-07-14 18:20 ` [PATCH 5/5] tools/testing: add a test to check nsfs ioctl-s Andrey Vagin
2016-07-14 22:02 ` [PATCH 0/5 RFC] Add an interface to discover relationships between namespaces Andrey Vagin
2016-07-15  2:12   ` [PATCH 1/5] namespaces: move user_ns into ns_common Andrey Vagin
2016-07-15  2:12     ` [PATCH 2/5] kernel: add a helper to get an owning user namespace for a namespace Andrey Vagin
2016-07-24  5:03       ` Eric W. Biederman
2016-07-24  6:37         ` Andrew Vagin
2016-07-24 14:30           ` Eric W. Biederman [this message]
2016-07-24 17:05             ` W. Trevor King
2016-07-24 16:54       ` W. Trevor King
2016-07-15  2:12     ` [PATCH 3/5] nsfs: add ioctl to get an owning user namespace for ns file descriptor Andrey Vagin
2016-07-15  2:12     ` [PATCH 4/5] nsfs: add ioctl to get a parent namespace Andrey Vagin
2016-07-24  5:07       ` Eric W. Biederman
2016-07-15  2:12     ` [PATCH 5/5] tools/testing: add a test to check nsfs ioctl-s Andrey Vagin
2016-07-16  8:21     ` [PATCH 1/5] namespaces: move user_ns into ns_common kbuild test robot
2016-07-23 23:07     ` kbuild test robot
2016-07-24  5:00     ` Eric W. Biederman
2016-07-24  5:54       ` Andrew Vagin
     [not found]       ` <87k2gbmy02.fsf-JOvCrm2gF+uungPnsOpG7nhyD016LWXt@public.gmane.org>
2016-07-24  5:54         ` Andrew Vagin
2016-07-24  5:54       ` Andrew Vagin
2016-07-24  5:54       ` Andrew Vagin
2016-07-24  5:10   ` [PATCH 0/5 RFC] Add an interface to discover relationships between namespaces Eric W. Biederman
2016-07-26  2:07     ` Andrew Vagin
2016-07-21 14:41 ` Michael Kerrisk (man-pages)
2016-07-21 21:06   ` Andrew Vagin
     [not found]     ` <20160721210650.GA10989-1ViLX0X+lBJGNQ1M2rI3KwRV3xvJKrda@public.gmane.org>
2016-07-22  6:48       ` Michael Kerrisk (man-pages)
2016-07-22 18:25         ` Andrey Vagin
2016-07-25 11:47           ` Michael Kerrisk (man-pages)
2016-07-25 13:18             ` Eric W. Biederman
2016-07-25 14:46               ` Michael Kerrisk (man-pages)
2016-07-25 14:54                 ` Serge E. Hallyn
2016-07-25 15:17                   ` Eric W. Biederman
2016-07-25 14:59                 ` Eric W. Biederman
2016-07-26  2:54                   ` Andrew Vagin
2016-07-26  8:03                     ` Michael Kerrisk (man-pages)
2016-07-26 18:25                       ` Andrew Vagin
2016-07-26 18:32                         ` W. Trevor King
2016-07-26 19:11                           ` Andrew Vagin
2016-07-26 19:17                         ` Michael Kerrisk (man-pages)
2016-07-26 20:39                           ` Andrew Vagin
2016-07-28 10:45                             ` Michael Kerrisk (man-pages)
2016-07-28 12:56                               ` Eric W. Biederman
2016-07-28 19:00                                 ` Michael Kerrisk (man-pages)
2016-07-29 18:05                                   ` Eric W. Biederman
2016-07-31 21:31                                     ` Michael Kerrisk (man-pages)
2016-08-01 23:01                                     ` Andrew Vagin
2016-07-26 19:38                     ` Eric W. Biederman
2016-07-23 21:14 ` W. Trevor King
2016-07-23 21:38   ` James Bottomley
2016-07-23 21:58     ` W. Trevor King
2016-07-23 21:56       ` Eric W. Biederman
2016-07-23 22:34         ` W. Trevor King
2016-07-24  4:51           ` Eric W. Biederman
2016-08-01 18:20 ` Alban Crequy
2016-08-01 23:32   ` Andrew Vagin

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=87shuzglck.fsf@x220.int.ebiederm.org \
    --to=ebiederm@xmission.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=avagin@openvz.org \
    --cc=avagin@virtuozzo.com \
    --cc=containers@lists.linux-foundation.org \
    --cc=criu@openvz.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mtk.manpages@gmail.com \
    --cc=serge.hallyn@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).