diff options
Diffstat (limited to 'security/keys/key.c')
| -rw-r--r-- | security/keys/key.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index e50d264c9ad1..c1eac8084ade 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
| @@ -355,7 +355,7 @@ EXPORT_SYMBOL(key_alloc); | |||
| 355 | */ | 355 | */ |
| 356 | int key_payload_reserve(struct key *key, size_t datalen) | 356 | int key_payload_reserve(struct key *key, size_t datalen) |
| 357 | { | 357 | { |
| 358 | int delta = (int) datalen - key->datalen; | 358 | int delta = (int)datalen - key->datalen; |
| 359 | int ret = 0; | 359 | int ret = 0; |
| 360 | 360 | ||
| 361 | key_check(key); | 361 | key_check(key); |
| @@ -398,7 +398,8 @@ static int __key_instantiate_and_link(struct key *key, | |||
| 398 | const void *data, | 398 | const void *data, |
| 399 | size_t datalen, | 399 | size_t datalen, |
| 400 | struct key *keyring, | 400 | struct key *keyring, |
| 401 | struct key *authkey) | 401 | struct key *authkey, |
| 402 | struct keyring_list **_prealloc) | ||
| 402 | { | 403 | { |
| 403 | int ret, awaken; | 404 | int ret, awaken; |
| 404 | 405 | ||
| @@ -425,7 +426,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
| 425 | 426 | ||
| 426 | /* and link it into the destination keyring */ | 427 | /* and link it into the destination keyring */ |
| 427 | if (keyring) | 428 | if (keyring) |
| 428 | ret = __key_link(keyring, key); | 429 | __key_link(keyring, key, _prealloc); |
| 429 | 430 | ||
| 430 | /* disable the authorisation key */ | 431 | /* disable the authorisation key */ |
| 431 | if (authkey) | 432 | if (authkey) |
| @@ -453,15 +454,21 @@ int key_instantiate_and_link(struct key *key, | |||
| 453 | struct key *keyring, | 454 | struct key *keyring, |
| 454 | struct key *authkey) | 455 | struct key *authkey) |
| 455 | { | 456 | { |
| 457 | struct keyring_list *prealloc; | ||
| 456 | int ret; | 458 | int ret; |
| 457 | 459 | ||
| 458 | if (keyring) | 460 | if (keyring) { |
| 459 | down_write(&keyring->sem); | 461 | ret = __key_link_begin(keyring, key->type, key->description, |
| 462 | &prealloc); | ||
| 463 | if (ret < 0) | ||
| 464 | return ret; | ||
| 465 | } | ||
| 460 | 466 | ||
| 461 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); | 467 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, |
| 468 | &prealloc); | ||
| 462 | 469 | ||
| 463 | if (keyring) | 470 | if (keyring) |
| 464 | up_write(&keyring->sem); | 471 | __key_link_end(keyring, key->type, prealloc); |
| 465 | 472 | ||
| 466 | return ret; | 473 | return ret; |
| 467 | 474 | ||
| @@ -478,8 +485,9 @@ int key_negate_and_link(struct key *key, | |||
| 478 | struct key *keyring, | 485 | struct key *keyring, |
| 479 | struct key *authkey) | 486 | struct key *authkey) |
| 480 | { | 487 | { |
| 488 | struct keyring_list *prealloc; | ||
| 481 | struct timespec now; | 489 | struct timespec now; |
| 482 | int ret, awaken; | 490 | int ret, awaken, link_ret = 0; |
| 483 | 491 | ||
| 484 | key_check(key); | 492 | key_check(key); |
| 485 | key_check(keyring); | 493 | key_check(keyring); |
| @@ -488,7 +496,8 @@ int key_negate_and_link(struct key *key, | |||
| 488 | ret = -EBUSY; | 496 | ret = -EBUSY; |
| 489 | 497 | ||
| 490 | if (keyring) | 498 | if (keyring) |
| 491 | down_write(&keyring->sem); | 499 | link_ret = __key_link_begin(keyring, key->type, |
| 500 | key->description, &prealloc); | ||
| 492 | 501 | ||
| 493 | mutex_lock(&key_construction_mutex); | 502 | mutex_lock(&key_construction_mutex); |
| 494 | 503 | ||
| @@ -508,8 +517,8 @@ int key_negate_and_link(struct key *key, | |||
| 508 | ret = 0; | 517 | ret = 0; |
| 509 | 518 | ||
| 510 | /* and link it into the destination keyring */ | 519 | /* and link it into the destination keyring */ |
| 511 | if (keyring) | 520 | if (keyring && link_ret == 0) |
| 512 | ret = __key_link(keyring, key); | 521 | __key_link(keyring, key, &prealloc); |
| 513 | 522 | ||
| 514 | /* disable the authorisation key */ | 523 | /* disable the authorisation key */ |
| 515 | if (authkey) | 524 | if (authkey) |
| @@ -519,13 +528,13 @@ int key_negate_and_link(struct key *key, | |||
| 519 | mutex_unlock(&key_construction_mutex); | 528 | mutex_unlock(&key_construction_mutex); |
| 520 | 529 | ||
| 521 | if (keyring) | 530 | if (keyring) |
| 522 | up_write(&keyring->sem); | 531 | __key_link_end(keyring, key->type, prealloc); |
| 523 | 532 | ||
| 524 | /* wake up anyone waiting for a key to be constructed */ | 533 | /* wake up anyone waiting for a key to be constructed */ |
| 525 | if (awaken) | 534 | if (awaken) |
| 526 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); | 535 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
| 527 | 536 | ||
| 528 | return ret; | 537 | return ret == 0 ? link_ret : ret; |
| 529 | 538 | ||
| 530 | } /* end key_negate_and_link() */ | 539 | } /* end key_negate_and_link() */ |
| 531 | 540 | ||
| @@ -749,6 +758,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 749 | key_perm_t perm, | 758 | key_perm_t perm, |
| 750 | unsigned long flags) | 759 | unsigned long flags) |
| 751 | { | 760 | { |
| 761 | struct keyring_list *prealloc; | ||
| 752 | const struct cred *cred = current_cred(); | 762 | const struct cred *cred = current_cred(); |
| 753 | struct key_type *ktype; | 763 | struct key_type *ktype; |
| 754 | struct key *keyring, *key = NULL; | 764 | struct key *keyring, *key = NULL; |
| @@ -775,7 +785,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 775 | if (keyring->type != &key_type_keyring) | 785 | if (keyring->type != &key_type_keyring) |
| 776 | goto error_2; | 786 | goto error_2; |
| 777 | 787 | ||
| 778 | down_write(&keyring->sem); | 788 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
| 789 | if (ret < 0) | ||
| 790 | goto error_2; | ||
| 779 | 791 | ||
| 780 | /* if we're going to allocate a new key, we're going to have | 792 | /* if we're going to allocate a new key, we're going to have |
| 781 | * to modify the keyring */ | 793 | * to modify the keyring */ |
| @@ -817,7 +829,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 817 | } | 829 | } |
| 818 | 830 | ||
| 819 | /* instantiate it and link it into the target keyring */ | 831 | /* instantiate it and link it into the target keyring */ |
| 820 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); | 832 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, |
| 833 | &prealloc); | ||
| 821 | if (ret < 0) { | 834 | if (ret < 0) { |
| 822 | key_put(key); | 835 | key_put(key); |
| 823 | key_ref = ERR_PTR(ret); | 836 | key_ref = ERR_PTR(ret); |
| @@ -827,7 +840,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 827 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 840 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
| 828 | 841 | ||
| 829 | error_3: | 842 | error_3: |
| 830 | up_write(&keyring->sem); | 843 | __key_link_end(keyring, ktype, prealloc); |
| 831 | error_2: | 844 | error_2: |
| 832 | key_type_put(ktype); | 845 | key_type_put(ktype); |
| 833 | error: | 846 | error: |
| @@ -837,7 +850,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
| 837 | /* we found a matching key, so we're going to try to update it | 850 | /* we found a matching key, so we're going to try to update it |
| 838 | * - we can drop the locks first as we have the key pinned | 851 | * - we can drop the locks first as we have the key pinned |
| 839 | */ | 852 | */ |
| 840 | up_write(&keyring->sem); | 853 | __key_link_end(keyring, ktype, prealloc); |
| 841 | key_type_put(ktype); | 854 | key_type_put(ktype); |
| 842 | 855 | ||
| 843 | key_ref = __key_update(key_ref, payload, plen); | 856 | key_ref = __key_update(key_ref, payload, plen); |
