aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:20 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:20 -0500
commitbb952bb98a7e479262c7eb25d5592545a3af147d (patch)
tree9a2158c07a22a5fbddcec412944d2e7534eecc8f /security/keys/process_keys.c
parent275bb41e9d058fbb327e7642f077e1beaeac162e (diff)
CRED: Separate per-task-group keyrings from signal_struct
Separate per-task-group keyrings from signal_struct and dangle their anchor from the cred struct rather than the signal_struct. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c100
1 files changed, 40 insertions, 60 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 212601ebaa46..70ee93406f30 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -189,7 +189,7 @@ int install_process_keyring(void)
189 189
190 might_sleep(); 190 might_sleep();
191 191
192 if (!tsk->signal->process_keyring) { 192 if (!tsk->cred->tgcred->process_keyring) {
193 sprintf(buf, "_pid.%u", tsk->tgid); 193 sprintf(buf, "_pid.%u", tsk->tgid);
194 194
195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk,
@@ -200,12 +200,12 @@ int install_process_keyring(void)
200 } 200 }
201 201
202 /* attach keyring */ 202 /* attach keyring */
203 spin_lock_irq(&tsk->sighand->siglock); 203 spin_lock_irq(&tsk->cred->tgcred->lock);
204 if (!tsk->signal->process_keyring) { 204 if (!tsk->cred->tgcred->process_keyring) {
205 tsk->signal->process_keyring = keyring; 205 tsk->cred->tgcred->process_keyring = keyring;
206 keyring = NULL; 206 keyring = NULL;
207 } 207 }
208 spin_unlock_irq(&tsk->sighand->siglock); 208 spin_unlock_irq(&tsk->cred->tgcred->lock);
209 209
210 key_put(keyring); 210 key_put(keyring);
211 } 211 }
@@ -235,11 +235,11 @@ static int install_session_keyring(struct key *keyring)
235 sprintf(buf, "_ses.%u", tsk->tgid); 235 sprintf(buf, "_ses.%u", tsk->tgid);
236 236
237 flags = KEY_ALLOC_QUOTA_OVERRUN; 237 flags = KEY_ALLOC_QUOTA_OVERRUN;
238 if (tsk->signal->session_keyring) 238 if (tsk->cred->tgcred->session_keyring)
239 flags = KEY_ALLOC_IN_QUOTA; 239 flags = KEY_ALLOC_IN_QUOTA;
240 240
241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid,
242 flags, NULL); 242 tsk, flags, NULL);
243 if (IS_ERR(keyring)) 243 if (IS_ERR(keyring))
244 return PTR_ERR(keyring); 244 return PTR_ERR(keyring);
245 } 245 }
@@ -248,10 +248,10 @@ static int install_session_keyring(struct key *keyring)
248 } 248 }
249 249
250 /* install the keyring */ 250 /* install the keyring */
251 spin_lock_irq(&tsk->sighand->siglock); 251 spin_lock_irq(&tsk->cred->tgcred->lock);
252 old = tsk->signal->session_keyring; 252 old = tsk->cred->tgcred->session_keyring;
253 rcu_assign_pointer(tsk->signal->session_keyring, keyring); 253 rcu_assign_pointer(tsk->cred->tgcred->session_keyring, keyring);
254 spin_unlock_irq(&tsk->sighand->siglock); 254 spin_unlock_irq(&tsk->cred->tgcred->lock);
255 255
256 /* we're using RCU on the pointer, but there's no point synchronising 256 /* we're using RCU on the pointer, but there's no point synchronising
257 * on it if it didn't previously point to anything */ 257 * on it if it didn't previously point to anything */
@@ -266,28 +266,6 @@ static int install_session_keyring(struct key *keyring)
266 266
267/*****************************************************************************/ 267/*****************************************************************************/
268/* 268/*
269 * copy the keys in a thread group for fork without CLONE_THREAD
270 */
271int copy_thread_group_keys(struct task_struct *tsk)
272{
273 key_check(current->thread_group->session_keyring);
274 key_check(current->thread_group->process_keyring);
275
276 /* no process keyring yet */
277 tsk->signal->process_keyring = NULL;
278
279 /* same session keyring */
280 rcu_read_lock();
281 tsk->signal->session_keyring =
282 key_get(rcu_dereference(current->signal->session_keyring));
283 rcu_read_unlock();
284
285 return 0;
286
287} /* end copy_thread_group_keys() */
288
289/*****************************************************************************/
290/*
291 * copy the keys for fork 269 * copy the keys for fork
292 */ 270 */
293int copy_keys(unsigned long clone_flags, struct task_struct *tsk) 271int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
@@ -307,17 +285,6 @@ int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
307 285
308/*****************************************************************************/ 286/*****************************************************************************/
309/* 287/*
310 * dispose of thread group keys upon thread group destruction
311 */
312void exit_thread_group_keys(struct signal_struct *tg)
313{
314 key_put(tg->session_keyring);
315 key_put(tg->process_keyring);
316
317} /* end exit_thread_group_keys() */
318
319/*****************************************************************************/
320/*
321 * dispose of per-thread keys upon thread exit 288 * dispose of per-thread keys upon thread exit
322 */ 289 */
323void exit_keys(struct task_struct *tsk) 290void exit_keys(struct task_struct *tsk)
@@ -344,10 +311,10 @@ int exec_keys(struct task_struct *tsk)
344 key_put(old); 311 key_put(old);
345 312
346 /* discard the process keyring from a newly exec'd task */ 313 /* discard the process keyring from a newly exec'd task */
347 spin_lock_irq(&tsk->sighand->siglock); 314 spin_lock_irq(&tsk->cred->tgcred->lock);
348 old = tsk->signal->process_keyring; 315 old = tsk->cred->tgcred->process_keyring;
349 tsk->signal->process_keyring = NULL; 316 tsk->cred->tgcred->process_keyring = NULL;
350 spin_unlock_irq(&tsk->sighand->siglock); 317 spin_unlock_irq(&tsk->cred->tgcred->lock);
351 318
352 key_put(old); 319 key_put(old);
353 320
@@ -452,9 +419,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
452 } 419 }
453 420
454 /* search the process keyring second */ 421 /* search the process keyring second */
455 if (context->signal->process_keyring) { 422 if (cred->tgcred->process_keyring) {
456 key_ref = keyring_search_aux( 423 key_ref = keyring_search_aux(
457 make_key_ref(context->signal->process_keyring, 1), 424 make_key_ref(cred->tgcred->process_keyring, 1),
458 context, type, description, match); 425 context, type, description, match);
459 if (!IS_ERR(key_ref)) 426 if (!IS_ERR(key_ref))
460 goto found; 427 goto found;
@@ -473,11 +440,11 @@ key_ref_t search_process_keyrings(struct key_type *type,
473 } 440 }
474 441
475 /* search the session keyring */ 442 /* search the session keyring */
476 if (context->signal->session_keyring) { 443 if (cred->tgcred->session_keyring) {
477 rcu_read_lock(); 444 rcu_read_lock();
478 key_ref = keyring_search_aux( 445 key_ref = keyring_search_aux(
479 make_key_ref(rcu_dereference( 446 make_key_ref(rcu_dereference(
480 context->signal->session_keyring), 447 cred->tgcred->session_keyring),
481 1), 448 1),
482 context, type, description, match); 449 context, type, description, match);
483 rcu_read_unlock(); 450 rcu_read_unlock();
@@ -586,11 +553,13 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
586{ 553{
587 struct request_key_auth *rka; 554 struct request_key_auth *rka;
588 struct task_struct *t = current; 555 struct task_struct *t = current;
589 struct cred *cred = current_cred(); 556 struct cred *cred;
590 struct key *key; 557 struct key *key;
591 key_ref_t key_ref, skey_ref; 558 key_ref_t key_ref, skey_ref;
592 int ret; 559 int ret;
593 560
561try_again:
562 cred = get_current_cred();
594 key_ref = ERR_PTR(-ENOKEY); 563 key_ref = ERR_PTR(-ENOKEY);
595 564
596 switch (id) { 565 switch (id) {
@@ -604,6 +573,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
604 key = ERR_PTR(ret); 573 key = ERR_PTR(ret);
605 goto error; 574 goto error;
606 } 575 }
576 goto reget_creds;
607 } 577 }
608 578
609 key = cred->thread_keyring; 579 key = cred->thread_keyring;
@@ -612,7 +582,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
612 break; 582 break;
613 583
614 case KEY_SPEC_PROCESS_KEYRING: 584 case KEY_SPEC_PROCESS_KEYRING:
615 if (!t->signal->process_keyring) { 585 if (!cred->tgcred->process_keyring) {
616 if (!create) 586 if (!create)
617 goto error; 587 goto error;
618 588
@@ -621,15 +591,16 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
621 key = ERR_PTR(ret); 591 key = ERR_PTR(ret);
622 goto error; 592 goto error;
623 } 593 }
594 goto reget_creds;
624 } 595 }
625 596
626 key = t->signal->process_keyring; 597 key = cred->tgcred->process_keyring;
627 atomic_inc(&key->usage); 598 atomic_inc(&key->usage);
628 key_ref = make_key_ref(key, 1); 599 key_ref = make_key_ref(key, 1);
629 break; 600 break;
630 601
631 case KEY_SPEC_SESSION_KEYRING: 602 case KEY_SPEC_SESSION_KEYRING:
632 if (!t->signal->session_keyring) { 603 if (!cred->tgcred->session_keyring) {
633 /* always install a session keyring upon access if one 604 /* always install a session keyring upon access if one
634 * doesn't exist yet */ 605 * doesn't exist yet */
635 ret = install_user_keyrings(); 606 ret = install_user_keyrings();
@@ -639,10 +610,11 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
639 cred->user->session_keyring); 610 cred->user->session_keyring);
640 if (ret < 0) 611 if (ret < 0)
641 goto error; 612 goto error;
613 goto reget_creds;
642 } 614 }
643 615
644 rcu_read_lock(); 616 rcu_read_lock();
645 key = rcu_dereference(t->signal->session_keyring); 617 key = rcu_dereference(cred->tgcred->session_keyring);
646 atomic_inc(&key->usage); 618 atomic_inc(&key->usage);
647 rcu_read_unlock(); 619 rcu_read_unlock();
648 key_ref = make_key_ref(key, 1); 620 key_ref = make_key_ref(key, 1);
@@ -758,6 +730,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
758 goto invalid_key; 730 goto invalid_key;
759 731
760error: 732error:
733 put_cred(cred);
761 return key_ref; 734 return key_ref;
762 735
763invalid_key: 736invalid_key:
@@ -765,6 +738,12 @@ invalid_key:
765 key_ref = ERR_PTR(ret); 738 key_ref = ERR_PTR(ret);
766 goto error; 739 goto error;
767 740
741 /* if we attempted to install a keyring, then it may have caused new
742 * creds to be installed */
743reget_creds:
744 put_cred(cred);
745 goto try_again;
746
768} /* end lookup_user_key() */ 747} /* end lookup_user_key() */
769 748
770/*****************************************************************************/ 749/*****************************************************************************/
@@ -777,6 +756,7 @@ invalid_key:
777long join_session_keyring(const char *name) 756long join_session_keyring(const char *name)
778{ 757{
779 struct task_struct *tsk = current; 758 struct task_struct *tsk = current;
759 struct cred *cred = current->cred;
780 struct key *keyring; 760 struct key *keyring;
781 long ret; 761 long ret;
782 762
@@ -787,7 +767,7 @@ long join_session_keyring(const char *name)
787 goto error; 767 goto error;
788 768
789 rcu_read_lock(); 769 rcu_read_lock();
790 ret = rcu_dereference(tsk->signal->session_keyring)->serial; 770 ret = rcu_dereference(cred->tgcred->session_keyring)->serial;
791 rcu_read_unlock(); 771 rcu_read_unlock();
792 goto error; 772 goto error;
793 } 773 }
@@ -799,7 +779,7 @@ long join_session_keyring(const char *name)
799 keyring = find_keyring_by_name(name, false); 779 keyring = find_keyring_by_name(name, false);
800 if (PTR_ERR(keyring) == -ENOKEY) { 780 if (PTR_ERR(keyring) == -ENOKEY) {
801 /* not found - try and create a new one */ 781 /* not found - try and create a new one */
802 keyring = keyring_alloc(name, tsk->cred->uid, tsk->cred->gid, tsk, 782 keyring = keyring_alloc(name, cred->uid, cred->gid, tsk,
803 KEY_ALLOC_IN_QUOTA, NULL); 783 KEY_ALLOC_IN_QUOTA, NULL);
804 if (IS_ERR(keyring)) { 784 if (IS_ERR(keyring)) {
805 ret = PTR_ERR(keyring); 785 ret = PTR_ERR(keyring);