aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:19 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:19 -0500
commitc69e8d9c01db2adc503464993c358901c9af9de4 (patch)
treebed94aaa9aeb7a7834d1c880f72b62a11a752c78 /security/keys
parent86a264abe542cfececb4df129bc45a0338d8cdb9 (diff)
CRED: Use RCU to access another task's creds and to release a task's own creds
Use RCU to access another task's creds and to release a task's own creds. This means that it will be possible for the credentials of a task to be replaced without another task (a) requiring a full lock to read them, and (b) seeing deallocated memory. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/permission.c10
-rw-r--r--security/keys/process_keys.c24
2 files changed, 20 insertions, 14 deletions
diff --git a/security/keys/permission.c b/security/keys/permission.c
index baf3d5f31e71..13c36164f284 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -22,13 +22,16 @@ int key_task_permission(const key_ref_t key_ref,
22 struct task_struct *context, 22 struct task_struct *context,
23 key_perm_t perm) 23 key_perm_t perm)
24{ 24{
25 struct cred *cred = context->cred; 25 const struct cred *cred;
26 struct key *key; 26 struct key *key;
27 key_perm_t kperm; 27 key_perm_t kperm;
28 int ret; 28 int ret;
29 29
30 key = key_ref_to_ptr(key_ref); 30 key = key_ref_to_ptr(key_ref);
31 31
32 rcu_read_lock();
33 cred = __task_cred(context);
34
32 /* use the second 8-bits of permissions for keys the caller owns */ 35 /* use the second 8-bits of permissions for keys the caller owns */
33 if (key->uid == cred->fsuid) { 36 if (key->uid == cred->fsuid) {
34 kperm = key->perm >> 16; 37 kperm = key->perm >> 16;
@@ -43,10 +46,7 @@ int key_task_permission(const key_ref_t key_ref,
43 goto use_these_perms; 46 goto use_these_perms;
44 } 47 }
45 48
46 spin_lock(&cred->lock);
47 ret = groups_search(cred->group_info, key->gid); 49 ret = groups_search(cred->group_info, key->gid);
48 spin_unlock(&cred->lock);
49
50 if (ret) { 50 if (ret) {
51 kperm = key->perm >> 8; 51 kperm = key->perm >> 8;
52 goto use_these_perms; 52 goto use_these_perms;
@@ -57,6 +57,8 @@ int key_task_permission(const key_ref_t key_ref,
57 kperm = key->perm; 57 kperm = key->perm;
58 58
59use_these_perms: 59use_these_perms:
60 rcu_read_lock();
61
60 /* use the top 8-bits of permissions for keys the caller possesses 62 /* use the top 8-bits of permissions for keys the caller possesses
61 * - possessor permissions are additive with other permissions 63 * - possessor permissions are additive with other permissions
62 */ 64 */
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index ce8ac6073d57..212601ebaa46 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -412,10 +412,13 @@ key_ref_t search_process_keyrings(struct key_type *type,
412 struct task_struct *context) 412 struct task_struct *context)
413{ 413{
414 struct request_key_auth *rka; 414 struct request_key_auth *rka;
415 struct cred *cred;
415 key_ref_t key_ref, ret, err; 416 key_ref_t key_ref, ret, err;
416 417
417 might_sleep(); 418 might_sleep();
418 419
420 cred = get_task_cred(context);
421
419 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 422 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
420 * searchable, but we failed to find a key or we found a negative key; 423 * searchable, but we failed to find a key or we found a negative key;
421 * otherwise we want to return a sample error (probably -EACCES) if 424 * otherwise we want to return a sample error (probably -EACCES) if
@@ -428,9 +431,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
428 err = ERR_PTR(-EAGAIN); 431 err = ERR_PTR(-EAGAIN);
429 432
430 /* search the thread keyring first */ 433 /* search the thread keyring first */
431 if (context->cred->thread_keyring) { 434 if (cred->thread_keyring) {
432 key_ref = keyring_search_aux( 435 key_ref = keyring_search_aux(
433 make_key_ref(context->cred->thread_keyring, 1), 436 make_key_ref(cred->thread_keyring, 1),
434 context, type, description, match); 437 context, type, description, match);
435 if (!IS_ERR(key_ref)) 438 if (!IS_ERR(key_ref))
436 goto found; 439 goto found;
@@ -495,9 +498,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
495 } 498 }
496 } 499 }
497 /* or search the user-session keyring */ 500 /* or search the user-session keyring */
498 else if (context->cred->user->session_keyring) { 501 else if (cred->user->session_keyring) {
499 key_ref = keyring_search_aux( 502 key_ref = keyring_search_aux(
500 make_key_ref(context->cred->user->session_keyring, 1), 503 make_key_ref(cred->user->session_keyring, 1),
501 context, type, description, match); 504 context, type, description, match);
502 if (!IS_ERR(key_ref)) 505 if (!IS_ERR(key_ref))
503 goto found; 506 goto found;
@@ -519,20 +522,20 @@ key_ref_t search_process_keyrings(struct key_type *type,
519 * search the keyrings of the process mentioned there 522 * search the keyrings of the process mentioned there
520 * - we don't permit access to request_key auth keys via this method 523 * - we don't permit access to request_key auth keys via this method
521 */ 524 */
522 if (context->cred->request_key_auth && 525 if (cred->request_key_auth &&
523 context == current && 526 context == current &&
524 type != &key_type_request_key_auth 527 type != &key_type_request_key_auth
525 ) { 528 ) {
526 /* defend against the auth key being revoked */ 529 /* defend against the auth key being revoked */
527 down_read(&context->cred->request_key_auth->sem); 530 down_read(&cred->request_key_auth->sem);
528 531
529 if (key_validate(context->cred->request_key_auth) == 0) { 532 if (key_validate(cred->request_key_auth) == 0) {
530 rka = context->cred->request_key_auth->payload.data; 533 rka = cred->request_key_auth->payload.data;
531 534
532 key_ref = search_process_keyrings(type, description, 535 key_ref = search_process_keyrings(type, description,
533 match, rka->context); 536 match, rka->context);
534 537
535 up_read(&context->cred->request_key_auth->sem); 538 up_read(&cred->request_key_auth->sem);
536 539
537 if (!IS_ERR(key_ref)) 540 if (!IS_ERR(key_ref))
538 goto found; 541 goto found;
@@ -549,7 +552,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
549 break; 552 break;
550 } 553 }
551 } else { 554 } else {
552 up_read(&context->cred->request_key_auth->sem); 555 up_read(&cred->request_key_auth->sem);
553 } 556 }
554 } 557 }
555 558
@@ -557,6 +560,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
557 key_ref = ret ? ret : err; 560 key_ref = ret ? ret : err;
558 561
559found: 562found:
563 put_cred(cred);
560 return key_ref; 564 return key_ref;
561 565
562} /* end search_process_keyrings() */ 566} /* end search_process_keyrings() */