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 879669961b
	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 17f60a7da1
	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>
This commit is contained in:
David Howells 2011-08-22 14:09:00 +01:00 committed by James Morris
parent 6d528b0822
commit 012146d072
1 changed files with 14 additions and 2 deletions

View File

@ -646,6 +646,9 @@ void __init cred_init(void)
*/ */
struct cred *prepare_kernel_cred(struct task_struct *daemon) struct cred *prepare_kernel_cred(struct task_struct *daemon)
{ {
#ifdef CONFIG_KEYS
struct thread_group_cred *tgcred;
#endif
const struct cred *old; const struct cred *old;
struct cred *new; struct cred *new;
@ -653,6 +656,12 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
if (!new) if (!new)
return NULL; return NULL;
tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
if (!tgcred) {
kmem_cache_free(cred_jar, new);
return NULL;
}
kdebug("prepare_kernel_cred() alloc %p", new); kdebug("prepare_kernel_cred() alloc %p", new);
if (daemon) if (daemon)
@ -669,8 +678,11 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
get_group_info(new->group_info); get_group_info(new->group_info);
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
atomic_inc(&init_tgcred.usage); atomic_set(&tgcred->usage, 1);
new->tgcred = &init_tgcred; spin_lock_init(&tgcred->lock);
tgcred->process_keyring = NULL;
tgcred->session_keyring = NULL;
new->tgcred = tgcred;
new->request_key_auth = NULL; new->request_key_auth = NULL;
new->thread_keyring = NULL; new->thread_keyring = NULL;
new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;