diff options
Diffstat (limited to 'security/keys/key.c')
| -rw-r--r-- | security/keys/key.c | 81 |
1 files changed, 45 insertions, 36 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index fb89f9844465..2182be9e9309 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
| @@ -693,14 +693,15 @@ void key_type_put(struct key_type *ktype) | |||
| 693 | * - the key has an incremented refcount | 693 | * - the key has an incremented refcount |
| 694 | * - we need to put the key if we get an error | 694 | * - we need to put the key if we get an error |
| 695 | */ | 695 | */ |
| 696 | static inline struct key *__key_update(struct key *key, const void *payload, | 696 | static inline key_ref_t __key_update(key_ref_t key_ref, |
| 697 | size_t plen) | 697 | const void *payload, size_t plen) |
| 698 | { | 698 | { |
| 699 | struct key *key = key_ref_to_ptr(key_ref); | ||
| 699 | int ret; | 700 | int ret; |
| 700 | 701 | ||
| 701 | /* need write permission on the key to update it */ | 702 | /* need write permission on the key to update it */ |
| 702 | ret = -EACCES; | 703 | ret = -EACCES; |
| 703 | if (!key_permission(key, KEY_WRITE)) | 704 | if (!key_permission(key_ref, KEY_WRITE)) |
| 704 | goto error; | 705 | goto error; |
| 705 | 706 | ||
| 706 | ret = -EEXIST; | 707 | ret = -EEXIST; |
| @@ -719,12 +720,12 @@ static inline struct key *__key_update(struct key *key, const void *payload, | |||
| 719 | 720 | ||
| 720 | if (ret < 0) | 721 | if (ret < 0) |
| 721 | goto error; | 722 | goto error; |
| 722 | out: | 723 | out: |
| 723 | return key; | 724 | return key_ref; |
| 724 | 725 | ||
| 725 | error: | 726 | error: |
| 726 | key_put(key); | 727 | key_put(key); |
| 727 | key = ERR_PTR(ret); | 728 | key_ref = ERR_PTR(ret); |
| 728 | goto out; | 729 | goto out; |
| 729 | 730 | ||
| 730 | } /* end __key_update() */ | 731 | } /* end __key_update() */ |
| @@ -734,52 +735,56 @@ static inline struct key *__key_update(struct key *key, const void *payload, | |||
| 734 | * search the specified keyring for a key of the same description; if one is | 735 | * search the specified keyring for a key of the same description; if one is |
| 735 | * found, update it, otherwise add a new one | 736 | * found, update it, otherwise add a new one |
| 736 | */ | 737 | */ |
| 737 | struct key *key_create_or_update(struct key *keyring, | 738 | key_ref_t key_create_or_update(key_ref_t keyring_ref, |
| 738 | const char *type, | 739 | const char *type, |
| 739 | const char *description, | 740 | const char *description, |
| 740 | const void *payload, | 741 | const void *payload, |
| 741 | size_t plen, | 742 | size_t plen, |
| 742 | int not_in_quota) | 743 | int not_in_quota) |
| 743 | { | 744 | { |
| 744 | struct key_type *ktype; | 745 | struct key_type *ktype; |
| 745 | struct key *key = NULL; | 746 | struct key *keyring, *key = NULL; |
| 746 | key_perm_t perm; | 747 | key_perm_t perm; |
| 748 | key_ref_t key_ref; | ||
| 747 | int ret; | 749 | int ret; |
| 748 | 750 | ||
| 749 | key_check(keyring); | ||
| 750 | |||
| 751 | /* look up the key type to see if it's one of the registered kernel | 751 | /* look up the key type to see if it's one of the registered kernel |
| 752 | * types */ | 752 | * types */ |
| 753 | ktype = key_type_lookup(type); | 753 | ktype = key_type_lookup(type); |
| 754 | if (IS_ERR(ktype)) { | 754 | if (IS_ERR(ktype)) { |
| 755 | key = ERR_PTR(-ENODEV); | 755 | key_ref = ERR_PTR(-ENODEV); |
| 756 | goto error; | 756 | goto error; |
| 757 | } | 757 | } |
| 758 | 758 | ||
| 759 | ret = -EINVAL; | 759 | key_ref = ERR_PTR(-EINVAL); |
| 760 | if (!ktype->match || !ktype->instantiate) | 760 | if (!ktype->match || !ktype->instantiate) |
| 761 | goto error_2; | 761 | goto error_2; |
| 762 | 762 | ||
| 763 | keyring = key_ref_to_ptr(keyring_ref); | ||
| 764 | |||
| 765 | key_check(keyring); | ||
| 766 | |||
| 767 | down_write(&keyring->sem); | ||
| 768 | |||
| 769 | /* if we're going to allocate a new key, we're going to have | ||
| 770 | * to modify the keyring */ | ||
| 771 | key_ref = ERR_PTR(-EACCES); | ||
| 772 | if (!key_permission(keyring_ref, KEY_WRITE)) | ||
| 773 | goto error_3; | ||
| 774 | |||
| 763 | /* search for an existing key of the same type and description in the | 775 | /* search for an existing key of the same type and description in the |
| 764 | * destination keyring | 776 | * destination keyring |
| 765 | */ | 777 | */ |
| 766 | down_write(&keyring->sem); | 778 | key_ref = __keyring_search_one(keyring_ref, ktype, description, 0); |
| 767 | 779 | if (!IS_ERR(key_ref)) | |
| 768 | key = __keyring_search_one(keyring, ktype, description, 0); | ||
| 769 | if (!IS_ERR(key)) | ||
| 770 | goto found_matching_key; | 780 | goto found_matching_key; |
| 771 | 781 | ||
| 772 | /* if we're going to allocate a new key, we're going to have to modify | ||
| 773 | * the keyring */ | ||
| 774 | ret = -EACCES; | ||
| 775 | if (!key_permission(keyring, KEY_WRITE)) | ||
| 776 | goto error_3; | ||
| 777 | |||
| 778 | /* decide on the permissions we want */ | 782 | /* decide on the permissions we want */ |
| 779 | perm = KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; | 783 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; |
| 784 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; | ||
| 780 | 785 | ||
| 781 | if (ktype->read) | 786 | if (ktype->read) |
| 782 | perm |= KEY_USR_READ; | 787 | perm |= KEY_POS_READ | KEY_USR_READ; |
| 783 | 788 | ||
| 784 | if (ktype == &key_type_keyring || ktype->update) | 789 | if (ktype == &key_type_keyring || ktype->update) |
| 785 | perm |= KEY_USR_WRITE; | 790 | perm |= KEY_USR_WRITE; |
| @@ -788,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring, | |||
| 788 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 793 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
| 789 | perm, not_in_quota); | 794 | perm, not_in_quota); |
| 790 | if (IS_ERR(key)) { | 795 | if (IS_ERR(key)) { |
| 791 | ret = PTR_ERR(key); | 796 | key_ref = ERR_PTR(PTR_ERR(key)); |
| 792 | goto error_3; | 797 | goto error_3; |
| 793 | } | 798 | } |
| 794 | 799 | ||
| @@ -796,15 +801,18 @@ struct key *key_create_or_update(struct key *keyring, | |||
| 796 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); | 801 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); |
| 797 | if (ret < 0) { | 802 | if (ret < 0) { |
| 798 | key_put(key); | 803 | key_put(key); |
| 799 | key = ERR_PTR(ret); | 804 | key_ref = ERR_PTR(ret); |
| 805 | goto error_3; | ||
| 800 | } | 806 | } |
| 801 | 807 | ||
| 808 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | ||
| 809 | |||
| 802 | error_3: | 810 | error_3: |
| 803 | up_write(&keyring->sem); | 811 | up_write(&keyring->sem); |
| 804 | error_2: | 812 | error_2: |
| 805 | key_type_put(ktype); | 813 | key_type_put(ktype); |
| 806 | error: | 814 | error: |
| 807 | return key; | 815 | return key_ref; |
| 808 | 816 | ||
| 809 | found_matching_key: | 817 | found_matching_key: |
| 810 | /* we found a matching key, so we're going to try to update it | 818 | /* we found a matching key, so we're going to try to update it |
| @@ -813,7 +821,7 @@ struct key *key_create_or_update(struct key *keyring, | |||
| 813 | up_write(&keyring->sem); | 821 | up_write(&keyring->sem); |
| 814 | key_type_put(ktype); | 822 | key_type_put(ktype); |
| 815 | 823 | ||
| 816 | key = __key_update(key, payload, plen); | 824 | key_ref = __key_update(key_ref, payload, plen); |
| 817 | goto error; | 825 | goto error; |
| 818 | 826 | ||
| 819 | } /* end key_create_or_update() */ | 827 | } /* end key_create_or_update() */ |
| @@ -824,15 +832,16 @@ EXPORT_SYMBOL(key_create_or_update); | |||
| 824 | /* | 832 | /* |
| 825 | * update a key | 833 | * update a key |
| 826 | */ | 834 | */ |
| 827 | int key_update(struct key *key, const void *payload, size_t plen) | 835 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) |
| 828 | { | 836 | { |
| 837 | struct key *key = key_ref_to_ptr(key_ref); | ||
| 829 | int ret; | 838 | int ret; |
| 830 | 839 | ||
| 831 | key_check(key); | 840 | key_check(key); |
| 832 | 841 | ||
| 833 | /* the key must be writable */ | 842 | /* the key must be writable */ |
| 834 | ret = -EACCES; | 843 | ret = -EACCES; |
| 835 | if (!key_permission(key, KEY_WRITE)) | 844 | if (!key_permission(key_ref, KEY_WRITE)) |
| 836 | goto error; | 845 | goto error; |
| 837 | 846 | ||
| 838 | /* attempt to update it if supported */ | 847 | /* attempt to update it if supported */ |
