Commit 47a150edc2ae734c0f4bf50aa19499e23b9a46f8
Committed by
Linus Torvalds
1 parent
381e7863d9
Exists in
master
and in
39 other branches
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 { \ |
kernel/capability.c
... | ... | @@ -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 | +} |
kernel/cred.c
... | ... | @@ -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 |