diff options
Diffstat (limited to 'kernel/cred.c')
-rw-r--r-- | kernel/cred.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index 9a3e22641fe7..174fa84eca30 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Task credentials management - see Documentation/credentials.txt | 1 | /* Task credentials management - see Documentation/security/credentials.txt |
2 | * | 2 | * |
3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
@@ -35,7 +35,7 @@ static struct kmem_cache *cred_jar; | |||
35 | static struct thread_group_cred init_tgcred = { | 35 | static struct thread_group_cred init_tgcred = { |
36 | .usage = ATOMIC_INIT(2), | 36 | .usage = ATOMIC_INIT(2), |
37 | .tgid = 0, | 37 | .tgid = 0, |
38 | .lock = SPIN_LOCK_UNLOCKED, | 38 | .lock = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock), |
39 | }; | 39 | }; |
40 | #endif | 40 | #endif |
41 | 41 | ||
@@ -49,11 +49,12 @@ struct cred init_cred = { | |||
49 | .magic = CRED_MAGIC, | 49 | .magic = CRED_MAGIC, |
50 | #endif | 50 | #endif |
51 | .securebits = SECUREBITS_DEFAULT, | 51 | .securebits = SECUREBITS_DEFAULT, |
52 | .cap_inheritable = CAP_INIT_INH_SET, | 52 | .cap_inheritable = CAP_EMPTY_SET, |
53 | .cap_permitted = CAP_FULL_SET, | 53 | .cap_permitted = CAP_FULL_SET, |
54 | .cap_effective = CAP_INIT_EFF_SET, | 54 | .cap_effective = CAP_FULL_SET, |
55 | .cap_bset = CAP_INIT_BSET, | 55 | .cap_bset = CAP_FULL_SET, |
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, |
@@ -252,13 +253,13 @@ struct cred *cred_alloc_blank(void) | |||
252 | #endif | 253 | #endif |
253 | 254 | ||
254 | atomic_set(&new->usage, 1); | 255 | atomic_set(&new->usage, 1); |
256 | #ifdef CONFIG_DEBUG_CREDENTIALS | ||
257 | new->magic = CRED_MAGIC; | ||
258 | #endif | ||
255 | 259 | ||
256 | if (security_cred_alloc_blank(new, GFP_KERNEL) < 0) | 260 | if (security_cred_alloc_blank(new, GFP_KERNEL) < 0) |
257 | goto error; | 261 | goto error; |
258 | 262 | ||
259 | #ifdef CONFIG_DEBUG_CREDENTIALS | ||
260 | new->magic = CRED_MAGIC; | ||
261 | #endif | ||
262 | return new; | 263 | return new; |
263 | 264 | ||
264 | error: | 265 | error: |
@@ -325,7 +326,7 @@ EXPORT_SYMBOL(prepare_creds); | |||
325 | 326 | ||
326 | /* | 327 | /* |
327 | * Prepare credentials for current to perform an execve() | 328 | * Prepare credentials for current to perform an execve() |
328 | * - The caller must hold current->cred_guard_mutex | 329 | * - The caller must hold ->cred_guard_mutex |
329 | */ | 330 | */ |
330 | struct cred *prepare_exec_creds(void) | 331 | struct cred *prepare_exec_creds(void) |
331 | { | 332 | { |
@@ -384,8 +385,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
384 | struct cred *new; | 385 | struct cred *new; |
385 | int ret; | 386 | int ret; |
386 | 387 | ||
387 | mutex_init(&p->cred_guard_mutex); | ||
388 | |||
389 | if ( | 388 | if ( |
390 | #ifdef CONFIG_KEYS | 389 | #ifdef CONFIG_KEYS |
391 | !p->cred->thread_keyring && | 390 | !p->cred->thread_keyring && |
@@ -412,6 +411,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
412 | goto error_put; | 411 | goto error_put; |
413 | } | 412 | } |
414 | 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 | |||
415 | #ifdef CONFIG_KEYS | 419 | #ifdef CONFIG_KEYS |
416 | /* new threads get their own thread keyrings if their parent already | 420 | /* new threads get their own thread keyrings if their parent already |
417 | * had one */ | 421 | * had one */ |
@@ -659,6 +663,8 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
659 | validate_creds(old); | 663 | validate_creds(old); |
660 | 664 | ||
661 | *new = *old; | 665 | *new = *old; |
666 | atomic_set(&new->usage, 1); | ||
667 | set_cred_subscribers(new, 0); | ||
662 | get_uid(new->user); | 668 | get_uid(new->user); |
663 | get_group_info(new->group_info); | 669 | get_group_info(new->group_info); |
664 | 670 | ||
@@ -676,8 +682,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
676 | if (security_prepare_creds(new, old, GFP_KERNEL) < 0) | 682 | if (security_prepare_creds(new, old, GFP_KERNEL) < 0) |
677 | goto error; | 683 | goto error; |
678 | 684 | ||
679 | atomic_set(&new->usage, 1); | ||
680 | set_cred_subscribers(new, 0); | ||
681 | put_cred(old); | 685 | put_cred(old); |
682 | validate_creds(new); | 686 | validate_creds(new); |
683 | return new; | 687 | return new; |
@@ -750,7 +754,11 @@ bool creds_are_invalid(const struct cred *cred) | |||
750 | if (cred->magic != CRED_MAGIC) | 754 | if (cred->magic != CRED_MAGIC) |
751 | return true; | 755 | return true; |
752 | #ifdef CONFIG_SECURITY_SELINUX | 756 | #ifdef CONFIG_SECURITY_SELINUX |
753 | if (selinux_is_enabled()) { | 757 | /* |
758 | * cred->security == NULL if security_cred_alloc_blank() or | ||
759 | * security_prepare_creds() returned an error. | ||
760 | */ | ||
761 | if (selinux_is_enabled() && cred->security) { | ||
754 | if ((unsigned long) cred->security < PAGE_SIZE) | 762 | if ((unsigned long) cred->security < PAGE_SIZE) |
755 | return true; | 763 | return true; |
756 | if ((*(u32 *)cred->security & 0xffffff00) == | 764 | if ((*(u32 *)cred->security & 0xffffff00) == |