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 */ |