diff options
Diffstat (limited to 'security/keys')
| -rw-r--r-- | security/keys/internal.h | 6 | ||||
| -rw-r--r-- | security/keys/keyctl.c | 28 | ||||
| -rw-r--r-- | security/keys/process_keys.c | 6 | 
3 files changed, 12 insertions, 28 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h index b510a316874..c246ba5d43a 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -148,12 +148,8 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,  #define KEY_LOOKUP_PARTIAL	0x02  #define KEY_LOOKUP_FOR_UNLINK	0x04 -struct kludge {	/* this will die off very soon */ -	struct task_work twork; -	struct cred *cred; -};  extern long join_session_keyring(const char *name); -extern void key_change_session_keyring(struct task_work *twork); +extern void key_change_session_keyring(struct callback_head *twork);  extern struct work_struct key_gc_work;  extern unsigned key_gc_delay; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 26723caaad0..0291b3f9397 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1456,8 +1456,7 @@ long keyctl_session_to_parent(void)  {  	struct task_struct *me, *parent;  	const struct cred *mycred, *pcred; -	struct kludge *newwork; -	struct task_work *oldwork; +	struct callback_head *newwork, *oldwork;  	key_ref_t keyring_r;  	struct cred *cred;  	int ret; @@ -1467,20 +1466,17 @@ long keyctl_session_to_parent(void)  		return PTR_ERR(keyring_r);  	ret = -ENOMEM; -	newwork = kmalloc(sizeof(struct kludge), GFP_KERNEL); -	if (!newwork) -		goto error_keyring;  	/* our parent is going to need a new cred struct, a new tgcred struct  	 * and new security data, so we allocate them here to prevent ENOMEM in  	 * our parent */  	cred = cred_alloc_blank();  	if (!cred) -		goto error_newwork; +		goto error_keyring; +	newwork = &cred->rcu;  	cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); -	init_task_work(&newwork->twork, key_change_session_keyring); -	newwork->cred = cred; +	init_task_work(newwork, key_change_session_keyring);  	me = current;  	rcu_read_lock(); @@ -1529,24 +1525,18 @@ long keyctl_session_to_parent(void)  	/* the replacement session keyring is applied just prior to userspace  	 * restarting */ -	ret = task_work_add(parent, &newwork->twork, true); +	ret = task_work_add(parent, newwork, true);  	if (!ret)  		newwork = NULL;  unlock:  	write_unlock_irq(&tasklist_lock);  	rcu_read_unlock(); -	if (oldwork) { -		put_cred(container_of(oldwork, struct kludge, twork)->cred); -		kfree(oldwork); -	} -	if (newwork) { -		put_cred(newwork->cred); -		kfree(newwork); -	} +	if (oldwork) +		put_cred(container_of(oldwork, struct cred, rcu)); +	if (newwork) +		put_cred(cred);  	return ret; -error_newwork: -	kfree(newwork);  error_keyring:  	key_ref_put(keyring_r);  	return ret; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index c9b07c97d7f..54339cfd673 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -834,13 +834,11 @@ error:   * Replace a process's session keyring on behalf of one of its children when   * the target  process is about to resume userspace execution.   */ -void key_change_session_keyring(struct task_work *twork) +void key_change_session_keyring(struct callback_head *twork)  {  	const struct cred *old = current_cred(); -	struct kludge *p = container_of(twork, struct kludge, twork); -	struct cred *new = p->cred; +	struct cred *new = container_of(twork, struct cred, rcu); -	kfree(p);  	if (unlikely(current->flags & PF_EXITING)) {  		put_cred(new);  		return;  |