diff options
| author | James Morris <james.l.morris@oracle.com> | 2012-10-03 13:00:17 +1000 | 
|---|---|---|
| committer | James Morris <james.l.morris@oracle.com> | 2012-10-03 13:00:17 +1000 | 
| commit | 61d335dd27c67d656f114c091a46cf95cbeeb77c (patch) | |
| tree | 1e96f07fe903f992e1e2095f1a03b61243da59f0 /kernel | |
| parent | 87b526d349b04c31d7b3a40b434eb3f825d22305 (diff) | |
| parent | 4442d7704c7311d1c42383d365e0b883e0075975 (diff) | |
Merge branch 'security-next-keys' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/security-keys into next-queue
As requested by David.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cred.c | 127 | 
1 files changed, 15 insertions, 112 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index de728ac50d82..3f7ad1ec2ae4 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -30,17 +30,6 @@  static struct kmem_cache *cred_jar;  /* - * The common credentials for the initial task's thread group - */ -#ifdef CONFIG_KEYS -static struct thread_group_cred init_tgcred = { -	.usage	= ATOMIC_INIT(2), -	.tgid	= 0, -	.lock	= __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock), -}; -#endif - -/*   * The initial credentials for the initial task   */  struct cred init_cred = { @@ -65,9 +54,6 @@ struct cred init_cred = {  	.user			= INIT_USER,  	.user_ns		= &init_user_ns,  	.group_info		= &init_groups, -#ifdef CONFIG_KEYS -	.tgcred			= &init_tgcred, -#endif  };  static inline void set_cred_subscribers(struct cred *cred, int n) @@ -96,36 +82,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n)  }  /* - * Dispose of the shared task group credentials - */ -#ifdef CONFIG_KEYS -static void release_tgcred_rcu(struct rcu_head *rcu) -{ -	struct thread_group_cred *tgcred = -		container_of(rcu, struct thread_group_cred, rcu); - -	BUG_ON(atomic_read(&tgcred->usage) != 0); - -	key_put(tgcred->session_keyring); -	key_put(tgcred->process_keyring); -	kfree(tgcred); -} -#endif - -/* - * Release a set of thread group credentials. - */ -static void release_tgcred(struct cred *cred) -{ -#ifdef CONFIG_KEYS -	struct thread_group_cred *tgcred = cred->tgcred; - -	if (atomic_dec_and_test(&tgcred->usage)) -		call_rcu(&tgcred->rcu, release_tgcred_rcu); -#endif -} - -/*   * The RCU callback to actually dispose of a set of credentials   */  static void put_cred_rcu(struct rcu_head *rcu) @@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu)  #endif  	security_cred_free(cred); +	key_put(cred->session_keyring); +	key_put(cred->process_keyring);  	key_put(cred->thread_keyring);  	key_put(cred->request_key_auth); -	release_tgcred(cred);  	if (cred->group_info)  		put_group_info(cred->group_info);  	free_uid(cred->user); @@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void)  	if (!new)  		return NULL; -#ifdef CONFIG_KEYS -	new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL); -	if (!new->tgcred) { -		kmem_cache_free(cred_jar, new); -		return NULL; -	} -	atomic_set(&new->tgcred->usage, 1); -#endif -  	atomic_set(&new->usage, 1);  #ifdef CONFIG_DEBUG_CREDENTIALS  	new->magic = CRED_MAGIC; @@ -308,9 +256,10 @@ struct cred *prepare_creds(void)  	get_user_ns(new->user_ns);  #ifdef CONFIG_KEYS +	key_get(new->session_keyring); +	key_get(new->process_keyring);  	key_get(new->thread_keyring);  	key_get(new->request_key_auth); -	atomic_inc(&new->tgcred->usage);  #endif  #ifdef CONFIG_SECURITY @@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds);   */  struct cred *prepare_exec_creds(void)  { -	struct thread_group_cred *tgcred = NULL;  	struct cred *new; -#ifdef CONFIG_KEYS -	tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); -	if (!tgcred) -		return NULL; -#endif -  	new = prepare_creds(); -	if (!new) { -		kfree(tgcred); +	if (!new)  		return new; -	}  #ifdef CONFIG_KEYS  	/* newly exec'd tasks don't get a thread keyring */  	key_put(new->thread_keyring);  	new->thread_keyring = NULL; -	/* create a new per-thread-group creds for all this set of threads to -	 * share */ -	memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred)); - -	atomic_set(&tgcred->usage, 1); -	spin_lock_init(&tgcred->lock); -  	/* inherit the session keyring; new process keyring */ -	key_get(tgcred->session_keyring); -	tgcred->process_keyring = NULL; - -	release_tgcred(new); -	new->tgcred = tgcred; +	key_put(new->process_keyring); +	new->process_keyring = NULL;  #endif  	return new; @@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void)   */  int copy_creds(struct task_struct *p, unsigned long clone_flags)  { -#ifdef CONFIG_KEYS -	struct thread_group_cred *tgcred; -#endif  	struct cred *new;  	int ret; @@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)  			install_thread_keyring_to_cred(new);  	} -	/* we share the process and session keyrings between all the threads in -	 * a process - this is slightly icky as we violate COW credentials a -	 * bit */ +	/* The process keyring is only shared between the threads in a process; +	 * anything outside of those threads doesn't inherit. +	 */  	if (!(clone_flags & CLONE_THREAD)) { -		tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); -		if (!tgcred) { -			ret = -ENOMEM; -			goto error_put; -		} -		atomic_set(&tgcred->usage, 1); -		spin_lock_init(&tgcred->lock); -		tgcred->process_keyring = NULL; -		tgcred->session_keyring = key_get(new->tgcred->session_keyring); - -		release_tgcred(new); -		new->tgcred = tgcred; +		key_put(new->process_keyring); +		new->process_keyring = NULL;  	}  #endif @@ -643,9 +560,6 @@ void __init cred_init(void)   */  struct cred *prepare_kernel_cred(struct task_struct *daemon)  { -#ifdef CONFIG_KEYS -	struct thread_group_cred *tgcred; -#endif  	const struct cred *old;  	struct cred *new; @@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)  	if (!new)  		return NULL; -#ifdef CONFIG_KEYS -	tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); -	if (!tgcred) { -		kmem_cache_free(cred_jar, new); -		return NULL; -	} -#endif -  	kdebug("prepare_kernel_cred() alloc %p", new);  	if (daemon) @@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)  	get_group_info(new->group_info);  #ifdef CONFIG_KEYS -	atomic_set(&tgcred->usage, 1); -	spin_lock_init(&tgcred->lock); -	tgcred->process_keyring = NULL; -	tgcred->session_keyring = NULL; -	new->tgcred = tgcred; -	new->request_key_auth = NULL; +	new->session_keyring = NULL; +	new->process_keyring = NULL;  	new->thread_keyring = NULL; +	new->request_key_auth = NULL;  	new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;  #endif  | 
