diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:20 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:20 -0500 |
commit | bb952bb98a7e479262c7eb25d5592545a3af147d (patch) | |
tree | 9a2158c07a22a5fbddcec412944d2e7534eecc8f /security/keys/process_keys.c | |
parent | 275bb41e9d058fbb327e7642f077e1beaeac162e (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.c | 100 |
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 | */ | ||
271 | int 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 | */ |
293 | int copy_keys(unsigned long clone_flags, struct task_struct *tsk) | 271 | int 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 | */ | ||
312 | void 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 | */ |
323 | void exit_keys(struct task_struct *tsk) | 290 | void 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 | ||
561 | try_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 | ||
760 | error: | 732 | error: |
733 | put_cred(cred); | ||
761 | return key_ref; | 734 | return key_ref; |
762 | 735 | ||
763 | invalid_key: | 736 | invalid_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 */ | ||
743 | reget_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: | |||
777 | long join_session_keyring(const char *name) | 756 | long 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); |