aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/internal.h6
-rw-r--r--security/keys/keyctl.c28
-rw-r--r--security/keys/process_keys.c6
3 files changed, 12 insertions, 28 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index b510a316874a..c246ba5d43ab 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,
148#define KEY_LOOKUP_PARTIAL 0x02 148#define KEY_LOOKUP_PARTIAL 0x02
149#define KEY_LOOKUP_FOR_UNLINK 0x04 149#define KEY_LOOKUP_FOR_UNLINK 0x04
150 150
151struct kludge { /* this will die off very soon */
152 struct task_work twork;
153 struct cred *cred;
154};
155extern long join_session_keyring(const char *name); 151extern long join_session_keyring(const char *name);
156extern void key_change_session_keyring(struct task_work *twork); 152extern void key_change_session_keyring(struct callback_head *twork);
157 153
158extern struct work_struct key_gc_work; 154extern struct work_struct key_gc_work;
159extern unsigned key_gc_delay; 155extern unsigned key_gc_delay;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 26723caaad05..0291b3f9397c 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1456,8 +1456,7 @@ long keyctl_session_to_parent(void)
1456{ 1456{
1457 struct task_struct *me, *parent; 1457 struct task_struct *me, *parent;
1458 const struct cred *mycred, *pcred; 1458 const struct cred *mycred, *pcred;
1459 struct kludge *newwork; 1459 struct callback_head *newwork, *oldwork;
1460 struct task_work *oldwork;
1461 key_ref_t keyring_r; 1460 key_ref_t keyring_r;
1462 struct cred *cred; 1461 struct cred *cred;
1463 int ret; 1462 int ret;
@@ -1467,20 +1466,17 @@ long keyctl_session_to_parent(void)
1467 return PTR_ERR(keyring_r); 1466 return PTR_ERR(keyring_r);
1468 1467
1469 ret = -ENOMEM; 1468 ret = -ENOMEM;
1470 newwork = kmalloc(sizeof(struct kludge), GFP_KERNEL);
1471 if (!newwork)
1472 goto error_keyring;
1473 1469
1474 /* our parent is going to need a new cred struct, a new tgcred struct 1470 /* our parent is going to need a new cred struct, a new tgcred struct
1475 * and new security data, so we allocate them here to prevent ENOMEM in 1471 * and new security data, so we allocate them here to prevent ENOMEM in
1476 * our parent */ 1472 * our parent */
1477 cred = cred_alloc_blank(); 1473 cred = cred_alloc_blank();
1478 if (!cred) 1474 if (!cred)
1479 goto error_newwork; 1475 goto error_keyring;
1476 newwork = &cred->rcu;
1480 1477
1481 cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); 1478 cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
1482 init_task_work(&newwork->twork, key_change_session_keyring); 1479 init_task_work(newwork, key_change_session_keyring);
1483 newwork->cred = cred;
1484 1480
1485 me = current; 1481 me = current;
1486 rcu_read_lock(); 1482 rcu_read_lock();
@@ -1529,24 +1525,18 @@ long keyctl_session_to_parent(void)
1529 1525
1530 /* the replacement session keyring is applied just prior to userspace 1526 /* the replacement session keyring is applied just prior to userspace
1531 * restarting */ 1527 * restarting */
1532 ret = task_work_add(parent, &newwork->twork, true); 1528 ret = task_work_add(parent, newwork, true);
1533 if (!ret) 1529 if (!ret)
1534 newwork = NULL; 1530 newwork = NULL;
1535unlock: 1531unlock:
1536 write_unlock_irq(&tasklist_lock); 1532 write_unlock_irq(&tasklist_lock);
1537 rcu_read_unlock(); 1533 rcu_read_unlock();
1538 if (oldwork) { 1534 if (oldwork)
1539 put_cred(container_of(oldwork, struct kludge, twork)->cred); 1535 put_cred(container_of(oldwork, struct cred, rcu));
1540 kfree(oldwork); 1536 if (newwork)
1541 } 1537 put_cred(cred);
1542 if (newwork) {
1543 put_cred(newwork->cred);
1544 kfree(newwork);
1545 }
1546 return ret; 1538 return ret;
1547 1539
1548error_newwork:
1549 kfree(newwork);
1550error_keyring: 1540error_keyring:
1551 key_ref_put(keyring_r); 1541 key_ref_put(keyring_r);
1552 return ret; 1542 return ret;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index c9b07c97d7f2..54339cfd6734 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -834,13 +834,11 @@ error:
834 * Replace a process's session keyring on behalf of one of its children when 834 * Replace a process's session keyring on behalf of one of its children when
835 * the target process is about to resume userspace execution. 835 * the target process is about to resume userspace execution.
836 */ 836 */
837void key_change_session_keyring(struct task_work *twork) 837void key_change_session_keyring(struct callback_head *twork)
838{ 838{
839 const struct cred *old = current_cred(); 839 const struct cred *old = current_cred();
840 struct kludge *p = container_of(twork, struct kludge, twork); 840 struct cred *new = container_of(twork, struct cred, rcu);
841 struct cred *new = p->cred;
842 841
843 kfree(p);
844 if (unlikely(current->flags & PF_EXITING)) { 842 if (unlikely(current->flags & PF_EXITING)) {
845 put_cred(new); 843 put_cred(new);
846 return; 844 return;