Commit 47a150edc2ae734c0f4bf50aa19499e23b9a46f8

Authored by Serge E. Hallyn
Committed by Linus Torvalds
1 parent 381e7863d9

Cache user_ns in struct cred

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>
[ This makes a huge performance difference for acl_permission_check(),
  up to 30%.  And that is one of the hottest kernel functions for loads
  that are pathname-lookup heavy.  ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 4 changed files with 27 additions and 20 deletions Side-by-side Diff

include/linux/capability.h
... ... @@ -546,18 +546,7 @@
546 546 extern bool capable(int cap);
547 547 extern bool ns_capable(struct user_namespace *ns, int cap);
548 548 extern bool task_ns_capable(struct task_struct *t, int cap);
549   -
550   -/**
551   - * nsown_capable - Check superior capability to one's own user_ns
552   - * @cap: The capability in question
553   - *
554   - * Return true if the current task has the given superior capability
555   - * targeted at its own user namespace.
556   - */
557   -static inline bool nsown_capable(int cap)
558   -{
559   - return ns_capable(current_user_ns(), cap);
560   -}
  549 +extern bool nsown_capable(int cap);
561 550  
562 551 /* audit system wants to get cap info from files as well */
563 552 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
include/linux/cred.h
... ... @@ -146,6 +146,7 @@
146 146 void *security; /* subjective LSM security */
147 147 #endif
148 148 struct user_struct *user; /* real user ID subscription */
  149 + struct user_namespace *user_ns; /* cached user->user_ns */
149 150 struct group_info *group_info; /* supplementary groups for euid/fsgid */
150 151 struct rcu_head rcu; /* RCU deletion hook */
151 152 };
152 153  
... ... @@ -354,10 +355,15 @@
354 355 #define current_fsgid() (current_cred_xxx(fsgid))
355 356 #define current_cap() (current_cred_xxx(cap_effective))
356 357 #define current_user() (current_cred_xxx(user))
357   -#define _current_user_ns() (current_cred_xxx(user)->user_ns)
358 358 #define current_security() (current_cred_xxx(security))
359 359  
360   -extern struct user_namespace *current_user_ns(void);
  360 +#ifdef CONFIG_USER_NS
  361 +#define current_user_ns() (current_cred_xxx(user_ns))
  362 +#else
  363 +extern struct user_namespace init_user_ns;
  364 +#define current_user_ns() (&init_user_ns)
  365 +#endif
  366 +
361 367  
362 368 #define current_uid_gid(_uid, _gid) \
363 369 do { \
... ... @@ -399,4 +399,16 @@
399 399 return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
400 400 }
401 401 EXPORT_SYMBOL(task_ns_capable);
  402 +
  403 +/**
  404 + * nsown_capable - Check superior capability to one's own user_ns
  405 + * @cap: The capability in question
  406 + *
  407 + * Return true if the current task has the given superior capability
  408 + * targeted at its own user namespace.
  409 + */
  410 +bool nsown_capable(int cap)
  411 +{
  412 + return ns_capable(current_user_ns(), cap);
  413 +}
... ... @@ -54,6 +54,7 @@
54 54 .cap_effective = CAP_INIT_EFF_SET,
55 55 .cap_bset = CAP_INIT_BSET,
56 56 .user = INIT_USER,
  57 + .user_ns = &init_user_ns,
57 58 .group_info = &init_groups,
58 59 #ifdef CONFIG_KEYS
59 60 .tgcred = &init_tgcred,
... ... @@ -410,6 +411,11 @@
410 411 goto error_put;
411 412 }
412 413  
  414 + /* cache user_ns in cred. Doesn't need a refcount because it will
  415 + * stay pinned by cred->user
  416 + */
  417 + new->user_ns = new->user->user_ns;
  418 +
413 419 #ifdef CONFIG_KEYS
414 420 /* new threads get their own thread keyrings if their parent already
415 421 * had one */
... ... @@ -740,12 +746,6 @@
740 746 return security_kernel_create_files_as(new, inode);
741 747 }
742 748 EXPORT_SYMBOL(set_create_files_as);
743   -
744   -struct user_namespace *current_user_ns(void)
745   -{
746   - return _current_user_ns();
747   -}
748   -EXPORT_SYMBOL(current_user_ns);
749 749  
750 750 #ifdef CONFIG_DEBUG_CREDENTIALS
751 751