diff options
author | David Howells <dhowells@redhat.com> | 2011-08-22 09:09:00 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-08-22 19:57:35 -0400 |
commit | 012146d0728f85f7a5c7c36fb84bba33e2760507 (patch) | |
tree | 215ad5926013e6a71d1ea750a81596fa20028dcc /kernel/cred.c | |
parent | 6d528b082294f0ddabd6368297546a2c0b67d4fe (diff) |
CRED: Fix prepare_kernel_cred() to provide a new thread_group_cred struct
Fix prepare_kernel_cred() to provide a new, separate thread_group_cred struct
otherwise when using request_key() ____call_usermodehelper() calls
umh_keys_init() with the new creds pointing to init_tgcred, which
umh_keys_init() then blithely alters.
The problem can be demonstrated by:
# keyctl request2 user a debug:a @s
249681132
# grep req /proc/keys
079906a5 I--Q-- 1 perm 1f3f0000 0 0 keyring _req.249681132: 1/4
38ef1626 IR---- 1 expd 0b010000 0 0 .request_ key:ee1d4ec pid:4371 ci:1
The keyring _req.XXXX should have gone away, but something (init_tgcred) is
pinning it.
That key actually requested can then be removed and a new one created:
# keyctl unlink 249681132
1 links removed
[root@andromeda ~]# grep req /proc/keys
116cecac IR---- 1 expd 0b010000 0 0 .request_ key:eeb4911 pid:4379 ci:1
36d1cbf8 I--Q-- 1 perm 1f3f0000 0 0 keyring _req.250300689: 1/4
which causes the old _req keyring to go away and a new one to take its place.
This is a consequence of the changes in:
commit 879669961b11e7f40b518784863a259f735a72bf
Author: David Howells <dhowells@redhat.com>
Date: Fri Jun 17 11:25:59 2011 +0100
KEYS/DNS: Fix ____call_usermodehelper() to not lose the session keyring
and:
commit 17f60a7da150fdd0cfb9756f86a262daa72c835f
Author: Eric Paris <eparis@redhat.com>
Date: Fri Apr 1 17:07:50 2011 -0400
capabilites: allow the application of capability limits to usermode helpers
After this patch is applied, the _req keyring and the .request_key key are
cleaned up.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/cred.c')
-rw-r--r-- | kernel/cred.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index 174fa84eca30..f1e22556bc49 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -646,6 +646,9 @@ void __init cred_init(void) | |||
646 | */ | 646 | */ |
647 | struct cred *prepare_kernel_cred(struct task_struct *daemon) | 647 | struct cred *prepare_kernel_cred(struct task_struct *daemon) |
648 | { | 648 | { |
649 | #ifdef CONFIG_KEYS | ||
650 | struct thread_group_cred *tgcred; | ||
651 | #endif | ||
649 | const struct cred *old; | 652 | const struct cred *old; |
650 | struct cred *new; | 653 | struct cred *new; |
651 | 654 | ||
@@ -653,6 +656,12 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
653 | if (!new) | 656 | if (!new) |
654 | return NULL; | 657 | return NULL; |
655 | 658 | ||
659 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | ||
660 | if (!tgcred) { | ||
661 | kmem_cache_free(cred_jar, new); | ||
662 | return NULL; | ||
663 | } | ||
664 | |||
656 | kdebug("prepare_kernel_cred() alloc %p", new); | 665 | kdebug("prepare_kernel_cred() alloc %p", new); |
657 | 666 | ||
658 | if (daemon) | 667 | if (daemon) |
@@ -669,8 +678,11 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
669 | get_group_info(new->group_info); | 678 | get_group_info(new->group_info); |
670 | 679 | ||
671 | #ifdef CONFIG_KEYS | 680 | #ifdef CONFIG_KEYS |
672 | atomic_inc(&init_tgcred.usage); | 681 | atomic_set(&tgcred->usage, 1); |
673 | new->tgcred = &init_tgcred; | 682 | spin_lock_init(&tgcred->lock); |
683 | tgcred->process_keyring = NULL; | ||
684 | tgcred->session_keyring = NULL; | ||
685 | new->tgcred = tgcred; | ||
674 | new->request_key_auth = NULL; | 686 | new->request_key_auth = NULL; |
675 | new->thread_keyring = NULL; | 687 | new->thread_keyring = NULL; |
676 | new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 688 | new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |