All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Serge E. Hallyn" <serge@hallyn.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>,
	"Serge E. Hallyn" <serge.hallyn@canonical.com>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Daniel Lezcano <daniel.lezcano@free.fr>,
	David Howells <dhowells@redhat.com>,
	James Morris <jmorris@namei.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	containers@lists.linux-foundation.org,
	Al Viro <viro@zeniv.linux.org.uk>
Subject: Re: acl_permission_check: disgusting performance
Date: Fri, 13 May 2011 08:19:04 -0500	[thread overview]
Message-ID: <20110513131904.GA2519@mail.hallyn.com> (raw)
In-Reply-To: <BANLkTim3cy8Jf3URYTW+cbr3nrdWVbsmGw@mail.gmail.com>

Quoting Linus Torvalds (torvalds@linux-foundation.org):
> On Thu, May 12, 2011 at 9:02 PM, Serge E. Hallyn <serge@hallyn.com> wrote:
> >
> > I wonder how much this would help:  (only compile-tested)
> 
> So it should help a lot, but it breaks when CONFIG_USER_NS isn't even
> set (the case that Eric fixed.
> 
> So instead, do this:
> 
>  (a) get rid of the "_current_user_ns()" thing. There is no reason to
> have it, if it's directly off "current->cred", then it's cheaper to
> inline it than have a function just for two pointer indirections.

Unfortunately that was not there as an optimization but because it
gets around a circular dependency between cred.h and capability.h.
Ideally we would keep capability.h from having to know about struct
cred.

The two simplest solutions are to uninline nsown_capable() into
capability.c, and to move it from capability.h to cred.h, with the
expectation that all callers of nsown_capable() #include cred.h
(which they do).  I'm uninlining it here, hoping that the compiler
will inline it for us.

From: Serge E. Hallyn <serge.hallyn@canonical.com>
Date: Fri, 13 May 2011 04:27:54 +0100
Subject: [PATCH 1/1] Cache user_ns in struct cred (v2)

If !CONFIG_USERNS, have current_user_ns() defined to (&init_user_ns).

Get rid of _current_user_ns.  This requires nsown_capable() to be
defined in capability.c rather than as static inline in capability.h,
so do that.

Request_key needs init_user_ns defined at current_user_ns if
!CONFIG_USERNS, so forward-declare that in cred.h if !CONFIG_USERNS
at current_user_ns() define.

Compile-tested with and without CONFIG_USERNS.

Signed-off-by: Serge E. Hallyn <serge.hallyn@canonical.com>
---
 include/linux/capability.h |   13 +------------
 include/linux/cred.h       |   10 ++++++++--
 kernel/capability.c        |   12 ++++++++++++
 kernel/cred.c              |   12 ++++++------
 4 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/include/linux/capability.h b/include/linux/capability.h
index 16ee8b4..d4675af 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -546,18 +546,7 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap);
 extern bool capable(int cap);
 extern bool ns_capable(struct user_namespace *ns, int cap);
 extern bool task_ns_capable(struct task_struct *t, int cap);
-
-/**
- * nsown_capable - Check superior capability to one's own user_ns
- * @cap: The capability in question
- *
- * Return true if the current task has the given superior capability
- * targeted at its own user namespace.
- */
-static inline bool nsown_capable(int cap)
-{
-	return ns_capable(current_user_ns(), cap);
-}
+extern bool nsown_capable(int cap);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 9aeeb0b..be16b61 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -146,6 +146,7 @@ struct cred {
 	void		*security;	/* subjective LSM security */
 #endif
 	struct user_struct *user;	/* real user ID subscription */
+	struct user_namespace *user_ns; /* cached user->user_ns */
 	struct group_info *group_info;	/* supplementary groups for euid/fsgid */
 	struct rcu_head	rcu;		/* RCU deletion hook */
 };
@@ -354,10 +355,15 @@ static inline void put_cred(const struct cred *_cred)
 #define current_fsgid() 	(current_cred_xxx(fsgid))
 #define current_cap()		(current_cred_xxx(cap_effective))
 #define current_user()		(current_cred_xxx(user))
-#define _current_user_ns()	(current_cred_xxx(user)->user_ns)
 #define current_security()	(current_cred_xxx(security))
 
-extern struct user_namespace *current_user_ns(void);
+#ifdef CONFIG_USER_NS
+#define current_user_ns() (current_cred_xxx(user_ns))
+#else
+extern struct user_namespace init_user_ns;
+#define current_user_ns() (&init_user_ns)
+#endif
+
 
 #define current_uid_gid(_uid, _gid)		\
 do {						\
diff --git a/kernel/capability.c b/kernel/capability.c
index bf0c734..32a80e0 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -399,3 +399,15 @@ bool task_ns_capable(struct task_struct *t, int cap)
 	return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
 }
 EXPORT_SYMBOL(task_ns_capable);
+
+/**
+ * nsown_capable - Check superior capability to one's own user_ns
+ * @cap: The capability in question
+ *
+ * Return true if the current task has the given superior capability
+ * targeted at its own user namespace.
+ */
+bool nsown_capable(int cap)
+{
+	return ns_capable(current_user_ns(), cap);
+}
diff --git a/kernel/cred.c b/kernel/cred.c
index 5557b55..8093c16 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -54,6 +54,7 @@ struct cred init_cred = {
 	.cap_effective		= CAP_INIT_EFF_SET,
 	.cap_bset		= CAP_INIT_BSET,
 	.user			= INIT_USER,
+	.user_ns		= &init_user_ns,
 	.group_info		= &init_groups,
 #ifdef CONFIG_KEYS
 	.tgcred			= &init_tgcred,
@@ -410,6 +411,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
 			goto error_put;
 	}
 
+	/* cache user_ns in cred.  Doesn't need a refcount because it will
+	 * stay pinned by cred->user
+	 */
+	new->user_ns = new->user->user_ns;
+
 #ifdef CONFIG_KEYS
 	/* new threads get their own thread keyrings if their parent already
 	 * had one */
@@ -741,12 +747,6 @@ int set_create_files_as(struct cred *new, struct inode *inode)
 }
 EXPORT_SYMBOL(set_create_files_as);
 
-struct user_namespace *current_user_ns(void)
-{
-	return _current_user_ns();
-}
-EXPORT_SYMBOL(current_user_ns);
-
 #ifdef CONFIG_DEBUG_CREDENTIALS
 
 bool creds_are_invalid(const struct cred *cred)
-- 
1.7.0.4


  reply	other threads:[~2011-05-13 13:19 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-13  0:29 acl_permission_check: disgusting performance Linus Torvalds
2011-05-13  2:50 ` Serge E. Hallyn
2011-05-13  3:52   ` Eric W. Biederman
     [not found]     ` <m1iptf1cm2.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
2011-05-13  4:16       ` Linus Torvalds
2011-05-13  4:16     ` Linus Torvalds
     [not found]   ` <20110513025013.GA13209-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2011-05-13  3:52     ` Eric W. Biederman
2011-05-13  4:02     ` Serge E. Hallyn
2011-05-13  4:02   ` Serge E. Hallyn
     [not found]     ` <20110513040214.GA25270-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2011-05-13  4:26       ` Linus Torvalds
2011-05-13  4:26     ` Linus Torvalds
2011-05-13 13:19       ` Serge E. Hallyn [this message]
2011-05-13 16:16         ` Linus Torvalds
     [not found]           ` <BANLkTi=yyoMXNqGtVX9KxHjVaDVGW9uzdA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-05-13 16:29             ` Linus Torvalds
2011-05-13 16:29           ` Linus Torvalds
     [not found]             ` <BANLkTin-9SmqB=U7gmOFY2qkCLNd_Yn-sw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-05-13 18:30               ` Serge E. Hallyn
2011-05-13 18:30             ` Serge E. Hallyn
     [not found]         ` <20110513131904.GA2519-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2011-05-13 16:16           ` Linus Torvalds
     [not found]       ` <BANLkTim3cy8Jf3URYTW+cbr3nrdWVbsmGw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-05-13 13:19         ` Serge E. Hallyn
     [not found] ` <BANLkTi=nc3WGaASQm1Pc9byshLOmLf2bXQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-05-13  2:50   ` Serge E. Hallyn
  -- strict thread matches above, loose matches on Subject: below --
2011-05-13  0:29 Linus Torvalds

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=20110513131904.GA2519@mail.hallyn.com \
    --to=serge@hallyn.com \
    --cc=akpm@linux-foundation.org \
    --cc=containers@lists.linux-foundation.org \
    --cc=daniel.lezcano@free.fr \
    --cc=dhowells@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=jmorris@namei.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=serge.hallyn@canonical.com \
    --cc=torvalds@linux-foundation.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.