diff options
| author | Tony Luck <tony.luck@intel.com> | 2005-10-20 13:41:44 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2005-10-20 13:41:44 -0400 |
| commit | 9cec58dc138d6fcad9f447a19c8ff69f6540e667 (patch) | |
| tree | 4fe1cca94fdba8b705c87615bee06d3346f687ce /security/keys/process_keys.c | |
| parent | 17e5ad6c0ce5a970e2830d0de8bdd60a2f077d38 (diff) | |
| parent | ac9b9c667c2e1194e22ebe0a441ae1c37aaa9b90 (diff) | |
Update from upstream with manual merge of Yasunori Goto's
changes to swiotlb.c made in commit 281dd25cdc0d6903929b79183816d151ea626341
since this file has been moved from arch/ia64/lib/swiotlb.c to
lib/swiotlb.c
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'security/keys/process_keys.c')
| -rw-r--r-- | security/keys/process_keys.c | 164 |
1 files changed, 101 insertions, 63 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index c089f78fb94e..d42d2158ce13 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -39,7 +39,7 @@ struct key root_user_keyring = { | |||
| 39 | .type = &key_type_keyring, | 39 | .type = &key_type_keyring, |
| 40 | .user = &root_key_user, | 40 | .user = &root_key_user, |
| 41 | .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), | 41 | .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), |
| 42 | .perm = KEY_USR_ALL, | 42 | .perm = KEY_POS_ALL | KEY_USR_ALL, |
| 43 | .flags = 1 << KEY_FLAG_INSTANTIATED, | 43 | .flags = 1 << KEY_FLAG_INSTANTIATED, |
| 44 | .description = "_uid.0", | 44 | .description = "_uid.0", |
| 45 | #ifdef KEY_DEBUGGING | 45 | #ifdef KEY_DEBUGGING |
| @@ -54,7 +54,7 @@ struct key root_session_keyring = { | |||
| 54 | .type = &key_type_keyring, | 54 | .type = &key_type_keyring, |
| 55 | .user = &root_key_user, | 55 | .user = &root_key_user, |
| 56 | .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), | 56 | .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), |
| 57 | .perm = KEY_USR_ALL, | 57 | .perm = KEY_POS_ALL | KEY_USR_ALL, |
| 58 | .flags = 1 << KEY_FLAG_INSTANTIATED, | 58 | .flags = 1 << KEY_FLAG_INSTANTIATED, |
| 59 | .description = "_uid_ses.0", | 59 | .description = "_uid_ses.0", |
| 60 | #ifdef KEY_DEBUGGING | 60 | #ifdef KEY_DEBUGGING |
| @@ -98,7 +98,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
| 98 | user->session_keyring = session_keyring; | 98 | user->session_keyring = session_keyring; |
| 99 | ret = 0; | 99 | ret = 0; |
| 100 | 100 | ||
| 101 | error: | 101 | error: |
| 102 | return ret; | 102 | return ret; |
| 103 | 103 | ||
| 104 | } /* end alloc_uid_keyring() */ | 104 | } /* end alloc_uid_keyring() */ |
| @@ -156,7 +156,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
| 156 | ret = 0; | 156 | ret = 0; |
| 157 | 157 | ||
| 158 | key_put(old); | 158 | key_put(old); |
| 159 | error: | 159 | error: |
| 160 | return ret; | 160 | return ret; |
| 161 | 161 | ||
| 162 | } /* end install_thread_keyring() */ | 162 | } /* end install_thread_keyring() */ |
| @@ -193,7 +193,7 @@ int install_process_keyring(struct task_struct *tsk) | |||
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | ret = 0; | 195 | ret = 0; |
| 196 | error: | 196 | error: |
| 197 | return ret; | 197 | return ret; |
| 198 | 198 | ||
| 199 | } /* end install_process_keyring() */ | 199 | } /* end install_process_keyring() */ |
| @@ -236,7 +236,7 @@ static int install_session_keyring(struct task_struct *tsk, | |||
| 236 | /* we're using RCU on the pointer */ | 236 | /* we're using RCU on the pointer */ |
| 237 | synchronize_rcu(); | 237 | synchronize_rcu(); |
| 238 | key_put(old); | 238 | key_put(old); |
| 239 | error: | 239 | error: |
| 240 | return ret; | 240 | return ret; |
| 241 | 241 | ||
| 242 | } /* end install_session_keyring() */ | 242 | } /* end install_session_keyring() */ |
| @@ -376,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
| 376 | * - we return -EAGAIN if we didn't find any matching key | 376 | * - we return -EAGAIN if we didn't find any matching key |
| 377 | * - we return -ENOKEY if we found only negative matching keys | 377 | * - we return -ENOKEY if we found only negative matching keys |
| 378 | */ | 378 | */ |
| 379 | struct key *search_process_keyrings(struct key_type *type, | 379 | key_ref_t search_process_keyrings(struct key_type *type, |
| 380 | const void *description, | 380 | const void *description, |
| 381 | key_match_func_t match, | 381 | key_match_func_t match, |
| 382 | struct task_struct *context) | 382 | struct task_struct *context) |
| 383 | { | 383 | { |
| 384 | struct request_key_auth *rka; | 384 | struct request_key_auth *rka; |
| 385 | struct key *key, *ret, *err, *instkey; | 385 | key_ref_t key_ref, ret, err, instkey_ref; |
| 386 | 386 | ||
| 387 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 387 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
| 388 | * searchable, but we failed to find a key or we found a negative key; | 388 | * searchable, but we failed to find a key or we found a negative key; |
| @@ -391,46 +391,48 @@ struct key *search_process_keyrings(struct key_type *type, | |||
| 391 | * | 391 | * |
| 392 | * in terms of priority: success > -ENOKEY > -EAGAIN > other error | 392 | * in terms of priority: success > -ENOKEY > -EAGAIN > other error |
| 393 | */ | 393 | */ |
| 394 | key = NULL; | 394 | key_ref = NULL; |
| 395 | ret = NULL; | 395 | ret = NULL; |
| 396 | err = ERR_PTR(-EAGAIN); | 396 | err = ERR_PTR(-EAGAIN); |
| 397 | 397 | ||
| 398 | /* search the thread keyring first */ | 398 | /* search the thread keyring first */ |
| 399 | if (context->thread_keyring) { | 399 | if (context->thread_keyring) { |
| 400 | key = keyring_search_aux(context->thread_keyring, | 400 | key_ref = keyring_search_aux( |
| 401 | context, type, description, match); | 401 | make_key_ref(context->thread_keyring, 1), |
| 402 | if (!IS_ERR(key)) | 402 | context, type, description, match); |
| 403 | if (!IS_ERR(key_ref)) | ||
| 403 | goto found; | 404 | goto found; |
| 404 | 405 | ||
| 405 | switch (PTR_ERR(key)) { | 406 | switch (PTR_ERR(key_ref)) { |
| 406 | case -EAGAIN: /* no key */ | 407 | case -EAGAIN: /* no key */ |
| 407 | if (ret) | 408 | if (ret) |
| 408 | break; | 409 | break; |
| 409 | case -ENOKEY: /* negative key */ | 410 | case -ENOKEY: /* negative key */ |
| 410 | ret = key; | 411 | ret = key_ref; |
| 411 | break; | 412 | break; |
| 412 | default: | 413 | default: |
| 413 | err = key; | 414 | err = key_ref; |
| 414 | break; | 415 | break; |
| 415 | } | 416 | } |
| 416 | } | 417 | } |
| 417 | 418 | ||
| 418 | /* search the process keyring second */ | 419 | /* search the process keyring second */ |
| 419 | if (context->signal->process_keyring) { | 420 | if (context->signal->process_keyring) { |
| 420 | key = keyring_search_aux(context->signal->process_keyring, | 421 | key_ref = keyring_search_aux( |
| 421 | context, type, description, match); | 422 | make_key_ref(context->signal->process_keyring, 1), |
| 422 | if (!IS_ERR(key)) | 423 | context, type, description, match); |
| 424 | if (!IS_ERR(key_ref)) | ||
| 423 | goto found; | 425 | goto found; |
| 424 | 426 | ||
| 425 | switch (PTR_ERR(key)) { | 427 | switch (PTR_ERR(key_ref)) { |
| 426 | case -EAGAIN: /* no key */ | 428 | case -EAGAIN: /* no key */ |
| 427 | if (ret) | 429 | if (ret) |
| 428 | break; | 430 | break; |
| 429 | case -ENOKEY: /* negative key */ | 431 | case -ENOKEY: /* negative key */ |
| 430 | ret = key; | 432 | ret = key_ref; |
| 431 | break; | 433 | break; |
| 432 | default: | 434 | default: |
| 433 | err = key; | 435 | err = key_ref; |
| 434 | break; | 436 | break; |
| 435 | } | 437 | } |
| 436 | } | 438 | } |
| @@ -438,23 +440,25 @@ struct key *search_process_keyrings(struct key_type *type, | |||
| 438 | /* search the session keyring */ | 440 | /* search the session keyring */ |
| 439 | if (context->signal->session_keyring) { | 441 | if (context->signal->session_keyring) { |
| 440 | rcu_read_lock(); | 442 | rcu_read_lock(); |
| 441 | key = keyring_search_aux( | 443 | key_ref = keyring_search_aux( |
| 442 | rcu_dereference(context->signal->session_keyring), | 444 | make_key_ref(rcu_dereference( |
| 445 | context->signal->session_keyring), | ||
| 446 | 1), | ||
| 443 | context, type, description, match); | 447 | context, type, description, match); |
| 444 | rcu_read_unlock(); | 448 | rcu_read_unlock(); |
| 445 | 449 | ||
| 446 | if (!IS_ERR(key)) | 450 | if (!IS_ERR(key_ref)) |
| 447 | goto found; | 451 | goto found; |
| 448 | 452 | ||
| 449 | switch (PTR_ERR(key)) { | 453 | switch (PTR_ERR(key_ref)) { |
| 450 | case -EAGAIN: /* no key */ | 454 | case -EAGAIN: /* no key */ |
| 451 | if (ret) | 455 | if (ret) |
| 452 | break; | 456 | break; |
| 453 | case -ENOKEY: /* negative key */ | 457 | case -ENOKEY: /* negative key */ |
| 454 | ret = key; | 458 | ret = key_ref; |
| 455 | break; | 459 | break; |
| 456 | default: | 460 | default: |
| 457 | err = key; | 461 | err = key_ref; |
| 458 | break; | 462 | break; |
| 459 | } | 463 | } |
| 460 | 464 | ||
| @@ -465,51 +469,54 @@ struct key *search_process_keyrings(struct key_type *type, | |||
| 465 | goto no_key; | 469 | goto no_key; |
| 466 | 470 | ||
| 467 | rcu_read_lock(); | 471 | rcu_read_lock(); |
| 468 | instkey = __keyring_search_one( | 472 | instkey_ref = __keyring_search_one( |
| 469 | rcu_dereference(context->signal->session_keyring), | 473 | make_key_ref(rcu_dereference( |
| 474 | context->signal->session_keyring), | ||
| 475 | 1), | ||
| 470 | &key_type_request_key_auth, NULL, 0); | 476 | &key_type_request_key_auth, NULL, 0); |
| 471 | rcu_read_unlock(); | 477 | rcu_read_unlock(); |
| 472 | 478 | ||
| 473 | if (IS_ERR(instkey)) | 479 | if (IS_ERR(instkey_ref)) |
| 474 | goto no_key; | 480 | goto no_key; |
| 475 | 481 | ||
| 476 | rka = instkey->payload.data; | 482 | rka = key_ref_to_ptr(instkey_ref)->payload.data; |
| 477 | 483 | ||
| 478 | key = search_process_keyrings(type, description, match, | 484 | key_ref = search_process_keyrings(type, description, match, |
| 479 | rka->context); | 485 | rka->context); |
| 480 | key_put(instkey); | 486 | key_ref_put(instkey_ref); |
| 481 | 487 | ||
| 482 | if (!IS_ERR(key)) | 488 | if (!IS_ERR(key_ref)) |
| 483 | goto found; | 489 | goto found; |
| 484 | 490 | ||
| 485 | switch (PTR_ERR(key)) { | 491 | switch (PTR_ERR(key_ref)) { |
| 486 | case -EAGAIN: /* no key */ | 492 | case -EAGAIN: /* no key */ |
| 487 | if (ret) | 493 | if (ret) |
| 488 | break; | 494 | break; |
| 489 | case -ENOKEY: /* negative key */ | 495 | case -ENOKEY: /* negative key */ |
| 490 | ret = key; | 496 | ret = key_ref; |
| 491 | break; | 497 | break; |
| 492 | default: | 498 | default: |
| 493 | err = key; | 499 | err = key_ref; |
| 494 | break; | 500 | break; |
| 495 | } | 501 | } |
| 496 | } | 502 | } |
| 497 | /* or search the user-session keyring */ | 503 | /* or search the user-session keyring */ |
| 498 | else { | 504 | else { |
| 499 | key = keyring_search_aux(context->user->session_keyring, | 505 | key_ref = keyring_search_aux( |
| 500 | context, type, description, match); | 506 | make_key_ref(context->user->session_keyring, 1), |
| 501 | if (!IS_ERR(key)) | 507 | context, type, description, match); |
| 508 | if (!IS_ERR(key_ref)) | ||
| 502 | goto found; | 509 | goto found; |
| 503 | 510 | ||
| 504 | switch (PTR_ERR(key)) { | 511 | switch (PTR_ERR(key_ref)) { |
| 505 | case -EAGAIN: /* no key */ | 512 | case -EAGAIN: /* no key */ |
| 506 | if (ret) | 513 | if (ret) |
| 507 | break; | 514 | break; |
| 508 | case -ENOKEY: /* negative key */ | 515 | case -ENOKEY: /* negative key */ |
| 509 | ret = key; | 516 | ret = key_ref; |
| 510 | break; | 517 | break; |
| 511 | default: | 518 | default: |
| 512 | err = key; | 519 | err = key_ref; |
| 513 | break; | 520 | break; |
| 514 | } | 521 | } |
| 515 | } | 522 | } |
| @@ -517,29 +524,40 @@ struct key *search_process_keyrings(struct key_type *type, | |||
| 517 | 524 | ||
| 518 | no_key: | 525 | no_key: |
| 519 | /* no key - decide on the error we're going to go for */ | 526 | /* no key - decide on the error we're going to go for */ |
| 520 | key = ret ? ret : err; | 527 | key_ref = ret ? ret : err; |
| 521 | 528 | ||
| 522 | found: | 529 | found: |
| 523 | return key; | 530 | return key_ref; |
| 524 | 531 | ||
| 525 | } /* end search_process_keyrings() */ | 532 | } /* end search_process_keyrings() */ |
| 526 | 533 | ||
| 527 | /*****************************************************************************/ | 534 | /*****************************************************************************/ |
| 528 | /* | 535 | /* |
| 536 | * see if the key we're looking at is the target key | ||
| 537 | */ | ||
| 538 | static int lookup_user_key_possessed(const struct key *key, const void *target) | ||
| 539 | { | ||
| 540 | return key == target; | ||
| 541 | |||
| 542 | } /* end lookup_user_key_possessed() */ | ||
| 543 | |||
| 544 | /*****************************************************************************/ | ||
| 545 | /* | ||
| 529 | * lookup a key given a key ID from userspace with a given permissions mask | 546 | * lookup a key given a key ID from userspace with a given permissions mask |
| 530 | * - don't create special keyrings unless so requested | 547 | * - don't create special keyrings unless so requested |
| 531 | * - partially constructed keys aren't found unless requested | 548 | * - partially constructed keys aren't found unless requested |
| 532 | */ | 549 | */ |
| 533 | struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | 550 | key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, |
| 534 | int create, int partial, key_perm_t perm) | 551 | int create, int partial, key_perm_t perm) |
| 535 | { | 552 | { |
| 553 | key_ref_t key_ref, skey_ref; | ||
| 536 | struct key *key; | 554 | struct key *key; |
| 537 | int ret; | 555 | int ret; |
| 538 | 556 | ||
| 539 | if (!context) | 557 | if (!context) |
| 540 | context = current; | 558 | context = current; |
| 541 | 559 | ||
| 542 | key = ERR_PTR(-ENOKEY); | 560 | key_ref = ERR_PTR(-ENOKEY); |
| 543 | 561 | ||
| 544 | switch (id) { | 562 | switch (id) { |
| 545 | case KEY_SPEC_THREAD_KEYRING: | 563 | case KEY_SPEC_THREAD_KEYRING: |
| @@ -556,6 +574,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 556 | 574 | ||
| 557 | key = context->thread_keyring; | 575 | key = context->thread_keyring; |
| 558 | atomic_inc(&key->usage); | 576 | atomic_inc(&key->usage); |
| 577 | key_ref = make_key_ref(key, 1); | ||
| 559 | break; | 578 | break; |
| 560 | 579 | ||
| 561 | case KEY_SPEC_PROCESS_KEYRING: | 580 | case KEY_SPEC_PROCESS_KEYRING: |
| @@ -572,6 +591,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 572 | 591 | ||
| 573 | key = context->signal->process_keyring; | 592 | key = context->signal->process_keyring; |
| 574 | atomic_inc(&key->usage); | 593 | atomic_inc(&key->usage); |
| 594 | key_ref = make_key_ref(key, 1); | ||
| 575 | break; | 595 | break; |
| 576 | 596 | ||
| 577 | case KEY_SPEC_SESSION_KEYRING: | 597 | case KEY_SPEC_SESSION_KEYRING: |
| @@ -579,7 +599,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 579 | /* always install a session keyring upon access if one | 599 | /* always install a session keyring upon access if one |
| 580 | * doesn't exist yet */ | 600 | * doesn't exist yet */ |
| 581 | ret = install_session_keyring( | 601 | ret = install_session_keyring( |
| 582 | context, context->user->session_keyring); | 602 | context, context->user->session_keyring); |
| 583 | if (ret < 0) | 603 | if (ret < 0) |
| 584 | goto error; | 604 | goto error; |
| 585 | } | 605 | } |
| @@ -588,16 +608,19 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 588 | key = rcu_dereference(context->signal->session_keyring); | 608 | key = rcu_dereference(context->signal->session_keyring); |
| 589 | atomic_inc(&key->usage); | 609 | atomic_inc(&key->usage); |
| 590 | rcu_read_unlock(); | 610 | rcu_read_unlock(); |
| 611 | key_ref = make_key_ref(key, 1); | ||
| 591 | break; | 612 | break; |
| 592 | 613 | ||
| 593 | case KEY_SPEC_USER_KEYRING: | 614 | case KEY_SPEC_USER_KEYRING: |
| 594 | key = context->user->uid_keyring; | 615 | key = context->user->uid_keyring; |
| 595 | atomic_inc(&key->usage); | 616 | atomic_inc(&key->usage); |
| 617 | key_ref = make_key_ref(key, 1); | ||
| 596 | break; | 618 | break; |
| 597 | 619 | ||
| 598 | case KEY_SPEC_USER_SESSION_KEYRING: | 620 | case KEY_SPEC_USER_SESSION_KEYRING: |
| 599 | key = context->user->session_keyring; | 621 | key = context->user->session_keyring; |
| 600 | atomic_inc(&key->usage); | 622 | atomic_inc(&key->usage); |
| 623 | key_ref = make_key_ref(key, 1); | ||
| 601 | break; | 624 | break; |
| 602 | 625 | ||
| 603 | case KEY_SPEC_GROUP_KEYRING: | 626 | case KEY_SPEC_GROUP_KEYRING: |
| @@ -606,13 +629,28 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 606 | goto error; | 629 | goto error; |
| 607 | 630 | ||
| 608 | default: | 631 | default: |
| 609 | key = ERR_PTR(-EINVAL); | 632 | key_ref = ERR_PTR(-EINVAL); |
| 610 | if (id < 1) | 633 | if (id < 1) |
| 611 | goto error; | 634 | goto error; |
| 612 | 635 | ||
| 613 | key = key_lookup(id); | 636 | key = key_lookup(id); |
| 614 | if (IS_ERR(key)) | 637 | if (IS_ERR(key)) { |
| 638 | key_ref = ERR_PTR(PTR_ERR(key)); | ||
| 615 | goto error; | 639 | goto error; |
| 640 | } | ||
| 641 | |||
| 642 | key_ref = make_key_ref(key, 0); | ||
| 643 | |||
| 644 | /* check to see if we possess the key */ | ||
| 645 | skey_ref = search_process_keyrings(key->type, key, | ||
| 646 | lookup_user_key_possessed, | ||
| 647 | current); | ||
| 648 | |||
| 649 | if (!IS_ERR(skey_ref)) { | ||
| 650 | key_put(key); | ||
| 651 | key_ref = skey_ref; | ||
| 652 | } | ||
| 653 | |||
| 616 | break; | 654 | break; |
| 617 | } | 655 | } |
| 618 | 656 | ||
| @@ -630,15 +668,15 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, | |||
| 630 | /* check the permissions */ | 668 | /* check the permissions */ |
| 631 | ret = -EACCES; | 669 | ret = -EACCES; |
| 632 | 670 | ||
| 633 | if (!key_task_permission(key, context, perm)) | 671 | if (!key_task_permission(key_ref, context, perm)) |
| 634 | goto invalid_key; | 672 | goto invalid_key; |
| 635 | 673 | ||
| 636 | error: | 674 | error: |
| 637 | return key; | 675 | return key_ref; |
| 638 | 676 | ||
| 639 | invalid_key: | 677 | invalid_key: |
| 640 | key_put(key); | 678 | key_ref_put(key_ref); |
| 641 | key = ERR_PTR(ret); | 679 | key_ref = ERR_PTR(ret); |
| 642 | goto error; | 680 | goto error; |
| 643 | 681 | ||
| 644 | } /* end lookup_user_key() */ | 682 | } /* end lookup_user_key() */ |
| @@ -694,9 +732,9 @@ long join_session_keyring(const char *name) | |||
| 694 | ret = keyring->serial; | 732 | ret = keyring->serial; |
| 695 | key_put(keyring); | 733 | key_put(keyring); |
| 696 | 734 | ||
| 697 | error2: | 735 | error2: |
| 698 | up(&key_session_sem); | 736 | up(&key_session_sem); |
| 699 | error: | 737 | error: |
| 700 | return ret; | 738 | return ret; |
| 701 | 739 | ||
| 702 | } /* end join_session_keyring() */ | 740 | } /* end join_session_keyring() */ |
