diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
| commit | bb799d3b980eb803ca2da4a4eefbd9308f8d988a (patch) | |
| tree | 69fbe0cd6d47b23a50f5e1d87bf7489532fae149 /security/keys/process_keys.c | |
| parent | 919fc6e34831d1c2b58bfb5ae261dc3facc9b269 (diff) | |
| parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) | |
Merge tag 'v3.13-rc4' into core/locking
Merge Linux 3.13-rc4, to refresh this rather old tree with the latest fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'security/keys/process_keys.c')
| -rw-r--r-- | security/keys/process_keys.c | 141 |
1 files changed, 76 insertions, 65 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 42defae1e161..0cf8a130a267 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -235,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
| 235 | if (IS_ERR(keyring)) | 235 | if (IS_ERR(keyring)) |
| 236 | return PTR_ERR(keyring); | 236 | return PTR_ERR(keyring); |
| 237 | } else { | 237 | } else { |
| 238 | atomic_inc(&keyring->usage); | 238 | __key_get(keyring); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | /* install the keyring */ | 241 | /* install the keyring */ |
| @@ -319,11 +319,7 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
| 319 | * In the case of a successful return, the possession attribute is set on the | 319 | * In the case of a successful return, the possession attribute is set on the |
| 320 | * returned key reference. | 320 | * returned key reference. |
| 321 | */ | 321 | */ |
| 322 | key_ref_t search_my_process_keyrings(struct key_type *type, | 322 | key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) |
| 323 | const void *description, | ||
| 324 | key_match_func_t match, | ||
| 325 | bool no_state_check, | ||
| 326 | const struct cred *cred) | ||
| 327 | { | 323 | { |
| 328 | key_ref_t key_ref, ret, err; | 324 | key_ref_t key_ref, ret, err; |
| 329 | 325 | ||
| @@ -339,10 +335,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
| 339 | err = ERR_PTR(-EAGAIN); | 335 | err = ERR_PTR(-EAGAIN); |
| 340 | 336 | ||
| 341 | /* search the thread keyring first */ | 337 | /* search the thread keyring first */ |
| 342 | if (cred->thread_keyring) { | 338 | if (ctx->cred->thread_keyring) { |
| 343 | key_ref = keyring_search_aux( | 339 | key_ref = keyring_search_aux( |
| 344 | make_key_ref(cred->thread_keyring, 1), | 340 | make_key_ref(ctx->cred->thread_keyring, 1), ctx); |
| 345 | cred, type, description, match, no_state_check); | ||
| 346 | if (!IS_ERR(key_ref)) | 341 | if (!IS_ERR(key_ref)) |
| 347 | goto found; | 342 | goto found; |
| 348 | 343 | ||
| @@ -358,10 +353,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
| 358 | } | 353 | } |
| 359 | 354 | ||
| 360 | /* search the process keyring second */ | 355 | /* search the process keyring second */ |
| 361 | if (cred->process_keyring) { | 356 | if (ctx->cred->process_keyring) { |
| 362 | key_ref = keyring_search_aux( | 357 | key_ref = keyring_search_aux( |
| 363 | make_key_ref(cred->process_keyring, 1), | 358 | make_key_ref(ctx->cred->process_keyring, 1), ctx); |
| 364 | cred, type, description, match, no_state_check); | ||
| 365 | if (!IS_ERR(key_ref)) | 359 | if (!IS_ERR(key_ref)) |
| 366 | goto found; | 360 | goto found; |
| 367 | 361 | ||
| @@ -379,11 +373,11 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
| 379 | } | 373 | } |
| 380 | 374 | ||
| 381 | /* search the session keyring */ | 375 | /* search the session keyring */ |
| 382 | if (cred->session_keyring) { | 376 | if (ctx->cred->session_keyring) { |
| 383 | rcu_read_lock(); | 377 | rcu_read_lock(); |
| 384 | key_ref = keyring_search_aux( | 378 | key_ref = keyring_search_aux( |
| 385 | make_key_ref(rcu_dereference(cred->session_keyring), 1), | 379 | make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1), |
| 386 | cred, type, description, match, no_state_check); | 380 | ctx); |
| 387 | rcu_read_unlock(); | 381 | rcu_read_unlock(); |
| 388 | 382 | ||
| 389 | if (!IS_ERR(key_ref)) | 383 | if (!IS_ERR(key_ref)) |
| @@ -402,10 +396,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
| 402 | } | 396 | } |
| 403 | } | 397 | } |
| 404 | /* or search the user-session keyring */ | 398 | /* or search the user-session keyring */ |
| 405 | else if (cred->user->session_keyring) { | 399 | else if (ctx->cred->user->session_keyring) { |
| 406 | key_ref = keyring_search_aux( | 400 | key_ref = keyring_search_aux( |
| 407 | make_key_ref(cred->user->session_keyring, 1), | 401 | make_key_ref(ctx->cred->user->session_keyring, 1), |
| 408 | cred, type, description, match, no_state_check); | 402 | ctx); |
| 409 | if (!IS_ERR(key_ref)) | 403 | if (!IS_ERR(key_ref)) |
| 410 | goto found; | 404 | goto found; |
| 411 | 405 | ||
| @@ -437,18 +431,14 @@ found: | |||
| 437 | * | 431 | * |
| 438 | * Return same as search_my_process_keyrings(). | 432 | * Return same as search_my_process_keyrings(). |
| 439 | */ | 433 | */ |
| 440 | key_ref_t search_process_keyrings(struct key_type *type, | 434 | key_ref_t search_process_keyrings(struct keyring_search_context *ctx) |
| 441 | const void *description, | ||
| 442 | key_match_func_t match, | ||
| 443 | const struct cred *cred) | ||
| 444 | { | 435 | { |
| 445 | struct request_key_auth *rka; | 436 | struct request_key_auth *rka; |
| 446 | key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; | 437 | key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; |
| 447 | 438 | ||
| 448 | might_sleep(); | 439 | might_sleep(); |
| 449 | 440 | ||
| 450 | key_ref = search_my_process_keyrings(type, description, match, | 441 | key_ref = search_my_process_keyrings(ctx); |
| 451 | false, cred); | ||
| 452 | if (!IS_ERR(key_ref)) | 442 | if (!IS_ERR(key_ref)) |
| 453 | goto found; | 443 | goto found; |
| 454 | err = key_ref; | 444 | err = key_ref; |
| @@ -457,18 +447,21 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
| 457 | * search the keyrings of the process mentioned there | 447 | * search the keyrings of the process mentioned there |
| 458 | * - we don't permit access to request_key auth keys via this method | 448 | * - we don't permit access to request_key auth keys via this method |
| 459 | */ | 449 | */ |
| 460 | if (cred->request_key_auth && | 450 | if (ctx->cred->request_key_auth && |
| 461 | cred == current_cred() && | 451 | ctx->cred == current_cred() && |
| 462 | type != &key_type_request_key_auth | 452 | ctx->index_key.type != &key_type_request_key_auth |
| 463 | ) { | 453 | ) { |
| 454 | const struct cred *cred = ctx->cred; | ||
| 455 | |||
| 464 | /* defend against the auth key being revoked */ | 456 | /* defend against the auth key being revoked */ |
| 465 | down_read(&cred->request_key_auth->sem); | 457 | down_read(&cred->request_key_auth->sem); |
| 466 | 458 | ||
| 467 | if (key_validate(cred->request_key_auth) == 0) { | 459 | if (key_validate(ctx->cred->request_key_auth) == 0) { |
| 468 | rka = cred->request_key_auth->payload.data; | 460 | rka = ctx->cred->request_key_auth->payload.data; |
| 469 | 461 | ||
| 470 | key_ref = search_process_keyrings(type, description, | 462 | ctx->cred = rka->cred; |
| 471 | match, rka->cred); | 463 | key_ref = search_process_keyrings(ctx); |
| 464 | ctx->cred = cred; | ||
| 472 | 465 | ||
| 473 | up_read(&cred->request_key_auth->sem); | 466 | up_read(&cred->request_key_auth->sem); |
| 474 | 467 | ||
| @@ -522,19 +515,23 @@ int lookup_user_key_possessed(const struct key *key, const void *target) | |||
| 522 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | 515 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
| 523 | key_perm_t perm) | 516 | key_perm_t perm) |
| 524 | { | 517 | { |
| 518 | struct keyring_search_context ctx = { | ||
| 519 | .match = lookup_user_key_possessed, | ||
| 520 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | ||
| 521 | KEYRING_SEARCH_LOOKUP_DIRECT), | ||
| 522 | }; | ||
| 525 | struct request_key_auth *rka; | 523 | struct request_key_auth *rka; |
| 526 | const struct cred *cred; | ||
| 527 | struct key *key; | 524 | struct key *key; |
| 528 | key_ref_t key_ref, skey_ref; | 525 | key_ref_t key_ref, skey_ref; |
| 529 | int ret; | 526 | int ret; |
| 530 | 527 | ||
| 531 | try_again: | 528 | try_again: |
| 532 | cred = get_current_cred(); | 529 | ctx.cred = get_current_cred(); |
| 533 | key_ref = ERR_PTR(-ENOKEY); | 530 | key_ref = ERR_PTR(-ENOKEY); |
| 534 | 531 | ||
| 535 | switch (id) { | 532 | switch (id) { |
| 536 | case KEY_SPEC_THREAD_KEYRING: | 533 | case KEY_SPEC_THREAD_KEYRING: |
| 537 | if (!cred->thread_keyring) { | 534 | if (!ctx.cred->thread_keyring) { |
| 538 | if (!(lflags & KEY_LOOKUP_CREATE)) | 535 | if (!(lflags & KEY_LOOKUP_CREATE)) |
| 539 | goto error; | 536 | goto error; |
| 540 | 537 | ||
| @@ -546,13 +543,13 @@ try_again: | |||
| 546 | goto reget_creds; | 543 | goto reget_creds; |
| 547 | } | 544 | } |
| 548 | 545 | ||
| 549 | key = cred->thread_keyring; | 546 | key = ctx.cred->thread_keyring; |
| 550 | atomic_inc(&key->usage); | 547 | __key_get(key); |
| 551 | key_ref = make_key_ref(key, 1); | 548 | key_ref = make_key_ref(key, 1); |
| 552 | break; | 549 | break; |
| 553 | 550 | ||
| 554 | case KEY_SPEC_PROCESS_KEYRING: | 551 | case KEY_SPEC_PROCESS_KEYRING: |
| 555 | if (!cred->process_keyring) { | 552 | if (!ctx.cred->process_keyring) { |
| 556 | if (!(lflags & KEY_LOOKUP_CREATE)) | 553 | if (!(lflags & KEY_LOOKUP_CREATE)) |
| 557 | goto error; | 554 | goto error; |
| 558 | 555 | ||
| @@ -564,13 +561,13 @@ try_again: | |||
| 564 | goto reget_creds; | 561 | goto reget_creds; |
| 565 | } | 562 | } |
| 566 | 563 | ||
| 567 | key = cred->process_keyring; | 564 | key = ctx.cred->process_keyring; |
| 568 | atomic_inc(&key->usage); | 565 | __key_get(key); |
| 569 | key_ref = make_key_ref(key, 1); | 566 | key_ref = make_key_ref(key, 1); |
| 570 | break; | 567 | break; |
| 571 | 568 | ||
| 572 | case KEY_SPEC_SESSION_KEYRING: | 569 | case KEY_SPEC_SESSION_KEYRING: |
| 573 | if (!cred->session_keyring) { | 570 | if (!ctx.cred->session_keyring) { |
| 574 | /* always install a session keyring upon access if one | 571 | /* always install a session keyring upon access if one |
| 575 | * doesn't exist yet */ | 572 | * doesn't exist yet */ |
| 576 | ret = install_user_keyrings(); | 573 | ret = install_user_keyrings(); |
| @@ -580,13 +577,13 @@ try_again: | |||
| 580 | ret = join_session_keyring(NULL); | 577 | ret = join_session_keyring(NULL); |
| 581 | else | 578 | else |
| 582 | ret = install_session_keyring( | 579 | ret = install_session_keyring( |
| 583 | cred->user->session_keyring); | 580 | ctx.cred->user->session_keyring); |
| 584 | 581 | ||
| 585 | if (ret < 0) | 582 | if (ret < 0) |
| 586 | goto error; | 583 | goto error; |
| 587 | goto reget_creds; | 584 | goto reget_creds; |
| 588 | } else if (cred->session_keyring == | 585 | } else if (ctx.cred->session_keyring == |
| 589 | cred->user->session_keyring && | 586 | ctx.cred->user->session_keyring && |
| 590 | lflags & KEY_LOOKUP_CREATE) { | 587 | lflags & KEY_LOOKUP_CREATE) { |
| 591 | ret = join_session_keyring(NULL); | 588 | ret = join_session_keyring(NULL); |
| 592 | if (ret < 0) | 589 | if (ret < 0) |
| @@ -595,33 +592,33 @@ try_again: | |||
| 595 | } | 592 | } |
| 596 | 593 | ||
| 597 | rcu_read_lock(); | 594 | rcu_read_lock(); |
| 598 | key = rcu_dereference(cred->session_keyring); | 595 | key = rcu_dereference(ctx.cred->session_keyring); |
| 599 | atomic_inc(&key->usage); | 596 | __key_get(key); |
| 600 | rcu_read_unlock(); | 597 | rcu_read_unlock(); |
| 601 | key_ref = make_key_ref(key, 1); | 598 | key_ref = make_key_ref(key, 1); |
| 602 | break; | 599 | break; |
| 603 | 600 | ||
| 604 | case KEY_SPEC_USER_KEYRING: | 601 | case KEY_SPEC_USER_KEYRING: |
| 605 | if (!cred->user->uid_keyring) { | 602 | if (!ctx.cred->user->uid_keyring) { |
| 606 | ret = install_user_keyrings(); | 603 | ret = install_user_keyrings(); |
| 607 | if (ret < 0) | 604 | if (ret < 0) |
| 608 | goto error; | 605 | goto error; |
| 609 | } | 606 | } |
| 610 | 607 | ||
| 611 | key = cred->user->uid_keyring; | 608 | key = ctx.cred->user->uid_keyring; |
| 612 | atomic_inc(&key->usage); | 609 | __key_get(key); |
| 613 | key_ref = make_key_ref(key, 1); | 610 | key_ref = make_key_ref(key, 1); |
| 614 | break; | 611 | break; |
| 615 | 612 | ||
| 616 | case KEY_SPEC_USER_SESSION_KEYRING: | 613 | case KEY_SPEC_USER_SESSION_KEYRING: |
| 617 | if (!cred->user->session_keyring) { | 614 | if (!ctx.cred->user->session_keyring) { |
| 618 | ret = install_user_keyrings(); | 615 | ret = install_user_keyrings(); |
| 619 | if (ret < 0) | 616 | if (ret < 0) |
| 620 | goto error; | 617 | goto error; |
| 621 | } | 618 | } |
| 622 | 619 | ||
| 623 | key = cred->user->session_keyring; | 620 | key = ctx.cred->user->session_keyring; |
| 624 | atomic_inc(&key->usage); | 621 | __key_get(key); |
| 625 | key_ref = make_key_ref(key, 1); | 622 | key_ref = make_key_ref(key, 1); |
| 626 | break; | 623 | break; |
| 627 | 624 | ||
| @@ -631,29 +628,29 @@ try_again: | |||
| 631 | goto error; | 628 | goto error; |
| 632 | 629 | ||
| 633 | case KEY_SPEC_REQKEY_AUTH_KEY: | 630 | case KEY_SPEC_REQKEY_AUTH_KEY: |
| 634 | key = cred->request_key_auth; | 631 | key = ctx.cred->request_key_auth; |
| 635 | if (!key) | 632 | if (!key) |
| 636 | goto error; | 633 | goto error; |
| 637 | 634 | ||
| 638 | atomic_inc(&key->usage); | 635 | __key_get(key); |
| 639 | key_ref = make_key_ref(key, 1); | 636 | key_ref = make_key_ref(key, 1); |
| 640 | break; | 637 | break; |
| 641 | 638 | ||
| 642 | case KEY_SPEC_REQUESTOR_KEYRING: | 639 | case KEY_SPEC_REQUESTOR_KEYRING: |
| 643 | if (!cred->request_key_auth) | 640 | if (!ctx.cred->request_key_auth) |
| 644 | goto error; | 641 | goto error; |
| 645 | 642 | ||
| 646 | down_read(&cred->request_key_auth->sem); | 643 | down_read(&ctx.cred->request_key_auth->sem); |
| 647 | if (test_bit(KEY_FLAG_REVOKED, | 644 | if (test_bit(KEY_FLAG_REVOKED, |
| 648 | &cred->request_key_auth->flags)) { | 645 | &ctx.cred->request_key_auth->flags)) { |
| 649 | key_ref = ERR_PTR(-EKEYREVOKED); | 646 | key_ref = ERR_PTR(-EKEYREVOKED); |
| 650 | key = NULL; | 647 | key = NULL; |
| 651 | } else { | 648 | } else { |
| 652 | rka = cred->request_key_auth->payload.data; | 649 | rka = ctx.cred->request_key_auth->payload.data; |
| 653 | key = rka->dest_keyring; | 650 | key = rka->dest_keyring; |
| 654 | atomic_inc(&key->usage); | 651 | __key_get(key); |
| 655 | } | 652 | } |
| 656 | up_read(&cred->request_key_auth->sem); | 653 | up_read(&ctx.cred->request_key_auth->sem); |
| 657 | if (!key) | 654 | if (!key) |
| 658 | goto error; | 655 | goto error; |
| 659 | key_ref = make_key_ref(key, 1); | 656 | key_ref = make_key_ref(key, 1); |
| @@ -673,9 +670,13 @@ try_again: | |||
| 673 | key_ref = make_key_ref(key, 0); | 670 | key_ref = make_key_ref(key, 0); |
| 674 | 671 | ||
| 675 | /* check to see if we possess the key */ | 672 | /* check to see if we possess the key */ |
| 676 | skey_ref = search_process_keyrings(key->type, key, | 673 | ctx.index_key.type = key->type; |
| 677 | lookup_user_key_possessed, | 674 | ctx.index_key.description = key->description; |
| 678 | cred); | 675 | ctx.index_key.desc_len = strlen(key->description); |
| 676 | ctx.match_data = key; | ||
| 677 | kdebug("check possessed"); | ||
| 678 | skey_ref = search_process_keyrings(&ctx); | ||
| 679 | kdebug("possessed=%p", skey_ref); | ||
| 679 | 680 | ||
| 680 | if (!IS_ERR(skey_ref)) { | 681 | if (!IS_ERR(skey_ref)) { |
| 681 | key_put(key); | 682 | key_put(key); |
| @@ -715,14 +716,14 @@ try_again: | |||
| 715 | goto invalid_key; | 716 | goto invalid_key; |
| 716 | 717 | ||
| 717 | /* check the permissions */ | 718 | /* check the permissions */ |
| 718 | ret = key_task_permission(key_ref, cred, perm); | 719 | ret = key_task_permission(key_ref, ctx.cred, perm); |
| 719 | if (ret < 0) | 720 | if (ret < 0) |
| 720 | goto invalid_key; | 721 | goto invalid_key; |
| 721 | 722 | ||
| 722 | key->last_used_at = current_kernel_time().tv_sec; | 723 | key->last_used_at = current_kernel_time().tv_sec; |
| 723 | 724 | ||
| 724 | error: | 725 | error: |
| 725 | put_cred(cred); | 726 | put_cred(ctx.cred); |
| 726 | return key_ref; | 727 | return key_ref; |
| 727 | 728 | ||
| 728 | invalid_key: | 729 | invalid_key: |
| @@ -733,7 +734,7 @@ invalid_key: | |||
| 733 | /* if we attempted to install a keyring, then it may have caused new | 734 | /* if we attempted to install a keyring, then it may have caused new |
| 734 | * creds to be installed */ | 735 | * creds to be installed */ |
| 735 | reget_creds: | 736 | reget_creds: |
| 736 | put_cred(cred); | 737 | put_cred(ctx.cred); |
| 737 | goto try_again; | 738 | goto try_again; |
| 738 | } | 739 | } |
| 739 | 740 | ||
| @@ -856,3 +857,13 @@ void key_change_session_keyring(struct callback_head *twork) | |||
| 856 | 857 | ||
| 857 | commit_creds(new); | 858 | commit_creds(new); |
| 858 | } | 859 | } |
| 860 | |||
| 861 | /* | ||
| 862 | * Make sure that root's user and user-session keyrings exist. | ||
| 863 | */ | ||
| 864 | static int __init init_root_keyring(void) | ||
| 865 | { | ||
| 866 | return install_user_keyrings(); | ||
| 867 | } | ||
| 868 | |||
| 869 | late_initcall(init_root_keyring); | ||
