diff options
| -rw-r--r-- | include/linux/capability.h | 13 | ||||
| -rw-r--r-- | include/linux/cred.h | 10 | ||||
| -rw-r--r-- | kernel/capability.c | 12 | ||||
| -rw-r--r-- | kernel/cred.c | 12 |
4 files changed, 27 insertions, 20 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h index 16ee8b49a200..d4675af963fa 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); | |||
| 546 | extern bool capable(int cap); | 546 | extern bool capable(int cap); |
| 547 | extern bool ns_capable(struct user_namespace *ns, int cap); | 547 | extern bool ns_capable(struct user_namespace *ns, int cap); |
| 548 | extern bool task_ns_capable(struct task_struct *t, int cap); | 548 | extern bool task_ns_capable(struct task_struct *t, int cap); |
| 549 | 549 | extern bool nsown_capable(int cap); | |
| 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 | } | ||
| 561 | 550 | ||
| 562 | /* audit system wants to get cap info from files as well */ | 551 | /* audit system wants to get cap info from files as well */ |
| 563 | extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps); | 552 | 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 9aeeb0ba2003..be16b61283cc 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
| @@ -146,6 +146,7 @@ struct cred { | |||
| 146 | void *security; /* subjective LSM security */ | 146 | void *security; /* subjective LSM security */ |
| 147 | #endif | 147 | #endif |
| 148 | struct user_struct *user; /* real user ID subscription */ | 148 | struct user_struct *user; /* real user ID subscription */ |
| 149 | struct user_namespace *user_ns; /* cached user->user_ns */ | ||
| 149 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ | 150 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ |
| 150 | struct rcu_head rcu; /* RCU deletion hook */ | 151 | struct rcu_head rcu; /* RCU deletion hook */ |
| 151 | }; | 152 | }; |
| @@ -354,10 +355,15 @@ static inline void put_cred(const struct cred *_cred) | |||
| 354 | #define current_fsgid() (current_cred_xxx(fsgid)) | 355 | #define current_fsgid() (current_cred_xxx(fsgid)) |
| 355 | #define current_cap() (current_cred_xxx(cap_effective)) | 356 | #define current_cap() (current_cred_xxx(cap_effective)) |
| 356 | #define current_user() (current_cred_xxx(user)) | 357 | #define current_user() (current_cred_xxx(user)) |
| 357 | #define _current_user_ns() (current_cred_xxx(user)->user_ns) | ||
| 358 | #define current_security() (current_cred_xxx(security)) | 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 | #define current_uid_gid(_uid, _gid) \ | 368 | #define current_uid_gid(_uid, _gid) \ |
| 363 | do { \ | 369 | do { \ |
diff --git a/kernel/capability.c b/kernel/capability.c index bf0c734d0c12..32a80e08ff4b 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
| @@ -399,3 +399,15 @@ bool task_ns_capable(struct task_struct *t, int cap) | |||
| 399 | return ns_capable(task_cred_xxx(t, user)->user_ns, cap); | 399 | return ns_capable(task_cred_xxx(t, user)->user_ns, cap); |
| 400 | } | 400 | } |
| 401 | EXPORT_SYMBOL(task_ns_capable); | 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 | } | ||
diff --git a/kernel/cred.c b/kernel/cred.c index 5557b55048df..8093c16b84b1 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
| @@ -54,6 +54,7 @@ struct cred init_cred = { | |||
| 54 | .cap_effective = CAP_INIT_EFF_SET, | 54 | .cap_effective = CAP_INIT_EFF_SET, |
| 55 | .cap_bset = CAP_INIT_BSET, | 55 | .cap_bset = CAP_INIT_BSET, |
| 56 | .user = INIT_USER, | 56 | .user = INIT_USER, |
| 57 | .user_ns = &init_user_ns, | ||
| 57 | .group_info = &init_groups, | 58 | .group_info = &init_groups, |
| 58 | #ifdef CONFIG_KEYS | 59 | #ifdef CONFIG_KEYS |
| 59 | .tgcred = &init_tgcred, | 60 | .tgcred = &init_tgcred, |
| @@ -410,6 +411,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
| 410 | goto error_put; | 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 | #ifdef CONFIG_KEYS | 419 | #ifdef CONFIG_KEYS |
| 414 | /* new threads get their own thread keyrings if their parent already | 420 | /* new threads get their own thread keyrings if their parent already |
| 415 | * had one */ | 421 | * had one */ |
| @@ -741,12 +747,6 @@ int set_create_files_as(struct cred *new, struct inode *inode) | |||
| 741 | } | 747 | } |
| 742 | EXPORT_SYMBOL(set_create_files_as); | 748 | EXPORT_SYMBOL(set_create_files_as); |
| 743 | 749 | ||
| 744 | struct user_namespace *current_user_ns(void) | ||
| 745 | { | ||
| 746 | return _current_user_ns(); | ||
| 747 | } | ||
| 748 | EXPORT_SYMBOL(current_user_ns); | ||
| 749 | |||
| 750 | #ifdef CONFIG_DEBUG_CREDENTIALS | 750 | #ifdef CONFIG_DEBUG_CREDENTIALS |
| 751 | 751 | ||
| 752 | bool creds_are_invalid(const struct cred *cred) | 752 | bool creds_are_invalid(const struct cred *cred) |
