Commit 16feef4340172b7dbb9cba60850e78fa6388adf1
1 parent
7e55ca6dcd
KEYS: Consolidate the concept of an 'index key' for key access
Consolidate the concept of an 'index key' for accessing keys. The index key is the search term needed to find a key directly - basically the key type and the key description. We can add to that the description length. This will be useful when turning a keyring into an associative array rather than just a pointer block. Signed-off-by: David Howells <dhowells@redhat.com>
Showing 5 changed files with 83 additions and 67 deletions Side-by-side Diff
include/linux/key.h
... | ... | @@ -82,6 +82,12 @@ |
82 | 82 | struct keyring_list; |
83 | 83 | struct keyring_name; |
84 | 84 | |
85 | +struct keyring_index_key { | |
86 | + struct key_type *type; | |
87 | + const char *description; | |
88 | + size_t desc_len; | |
89 | +}; | |
90 | + | |
85 | 91 | /*****************************************************************************/ |
86 | 92 | /* |
87 | 93 | * key reference with possession attribute handling |
... | ... | @@ -129,7 +135,6 @@ |
129 | 135 | struct list_head graveyard_link; |
130 | 136 | struct rb_node serial_node; |
131 | 137 | }; |
132 | - struct key_type *type; /* type of key */ | |
133 | 138 | struct rw_semaphore sem; /* change vs change sem */ |
134 | 139 | struct key_user *user; /* owner of this key */ |
135 | 140 | void *security; /* security data for this key */ |
136 | 141 | |
... | ... | @@ -163,12 +168,18 @@ |
163 | 168 | #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ |
164 | 169 | #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ |
165 | 170 | |
166 | - /* the description string | |
167 | - * - this is used to match a key against search criteria | |
168 | - * - this should be a printable string | |
171 | + /* the key type and key description string | |
172 | + * - the desc is used to match a key against search criteria | |
173 | + * - it should be a printable string | |
169 | 174 | * - eg: for krb5 AFS, this might be "afs@REDHAT.COM" |
170 | 175 | */ |
171 | - char *description; | |
176 | + union { | |
177 | + struct keyring_index_key index_key; | |
178 | + struct { | |
179 | + struct key_type *type; /* type of key */ | |
180 | + char *description; | |
181 | + }; | |
182 | + }; | |
172 | 183 | |
173 | 184 | /* type specific data |
174 | 185 | * - this is used by the keyring type to index the name |
security/keys/internal.h
... | ... | @@ -89,19 +89,17 @@ |
89 | 89 | extern void key_type_put(struct key_type *ktype); |
90 | 90 | |
91 | 91 | extern int __key_link_begin(struct key *keyring, |
92 | - const struct key_type *type, | |
93 | - const char *description, | |
92 | + const struct keyring_index_key *index_key, | |
94 | 93 | unsigned long *_prealloc); |
95 | 94 | extern int __key_link_check_live_key(struct key *keyring, struct key *key); |
96 | 95 | extern void __key_link(struct key *keyring, struct key *key, |
97 | 96 | unsigned long *_prealloc); |
98 | 97 | extern void __key_link_end(struct key *keyring, |
99 | - struct key_type *type, | |
98 | + const struct keyring_index_key *index_key, | |
100 | 99 | unsigned long prealloc); |
101 | 100 | |
102 | 101 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
103 | - const struct key_type *type, | |
104 | - const char *description, | |
102 | + const struct keyring_index_key *index_key, | |
105 | 103 | key_perm_t perm); |
106 | 104 | |
107 | 105 | extern struct key *keyring_search_instkey(struct key *keyring, |
security/keys/key.c
... | ... | @@ -242,8 +242,8 @@ |
242 | 242 | } |
243 | 243 | } |
244 | 244 | |
245 | - desclen = strlen(desc) + 1; | |
246 | - quotalen = desclen + type->def_datalen; | |
245 | + desclen = strlen(desc); | |
246 | + quotalen = desclen + 1 + type->def_datalen; | |
247 | 247 | |
248 | 248 | /* get hold of the key tracking for this user */ |
249 | 249 | user = key_user_lookup(uid); |
... | ... | @@ -277,7 +277,8 @@ |
277 | 277 | goto no_memory_2; |
278 | 278 | |
279 | 279 | if (desc) { |
280 | - key->description = kmemdup(desc, desclen, GFP_KERNEL); | |
280 | + key->index_key.desc_len = desclen; | |
281 | + key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); | |
281 | 282 | if (!key->description) |
282 | 283 | goto no_memory_3; |
283 | 284 | } |
... | ... | @@ -285,7 +286,7 @@ |
285 | 286 | atomic_set(&key->usage, 1); |
286 | 287 | init_rwsem(&key->sem); |
287 | 288 | lockdep_set_class(&key->sem, &type->lock_class); |
288 | - key->type = type; | |
289 | + key->index_key.type = type; | |
289 | 290 | key->user = user; |
290 | 291 | key->quotalen = quotalen; |
291 | 292 | key->datalen = type->def_datalen; |
... | ... | @@ -489,8 +490,7 @@ |
489 | 490 | } |
490 | 491 | |
491 | 492 | if (keyring) { |
492 | - ret = __key_link_begin(keyring, key->type, key->description, | |
493 | - &prealloc); | |
493 | + ret = __key_link_begin(keyring, &key->index_key, &prealloc); | |
494 | 494 | if (ret < 0) |
495 | 495 | goto error_free_preparse; |
496 | 496 | } |
... | ... | @@ -499,7 +499,7 @@ |
499 | 499 | &prealloc); |
500 | 500 | |
501 | 501 | if (keyring) |
502 | - __key_link_end(keyring, key->type, prealloc); | |
502 | + __key_link_end(keyring, &key->index_key, prealloc); | |
503 | 503 | |
504 | 504 | error_free_preparse: |
505 | 505 | if (key->type->preparse) |
... | ... | @@ -548,8 +548,7 @@ |
548 | 548 | ret = -EBUSY; |
549 | 549 | |
550 | 550 | if (keyring) |
551 | - link_ret = __key_link_begin(keyring, key->type, | |
552 | - key->description, &prealloc); | |
551 | + link_ret = __key_link_begin(keyring, &key->index_key, &prealloc); | |
553 | 552 | |
554 | 553 | mutex_lock(&key_construction_mutex); |
555 | 554 | |
... | ... | @@ -581,7 +580,7 @@ |
581 | 580 | mutex_unlock(&key_construction_mutex); |
582 | 581 | |
583 | 582 | if (keyring) |
584 | - __key_link_end(keyring, key->type, prealloc); | |
583 | + __key_link_end(keyring, &key->index_key, prealloc); | |
585 | 584 | |
586 | 585 | /* wake up anyone waiting for a key to be constructed */ |
587 | 586 | if (awaken) |
588 | 587 | |
589 | 588 | |
590 | 589 | |
... | ... | @@ -780,25 +779,27 @@ |
780 | 779 | key_perm_t perm, |
781 | 780 | unsigned long flags) |
782 | 781 | { |
783 | - unsigned long prealloc; | |
782 | + struct keyring_index_key index_key = { | |
783 | + .description = description, | |
784 | + }; | |
784 | 785 | struct key_preparsed_payload prep; |
785 | 786 | const struct cred *cred = current_cred(); |
786 | - struct key_type *ktype; | |
787 | + unsigned long prealloc; | |
787 | 788 | struct key *keyring, *key = NULL; |
788 | 789 | key_ref_t key_ref; |
789 | 790 | int ret; |
790 | 791 | |
791 | 792 | /* look up the key type to see if it's one of the registered kernel |
792 | 793 | * types */ |
793 | - ktype = key_type_lookup(type); | |
794 | - if (IS_ERR(ktype)) { | |
794 | + index_key.type = key_type_lookup(type); | |
795 | + if (IS_ERR(index_key.type)) { | |
795 | 796 | key_ref = ERR_PTR(-ENODEV); |
796 | 797 | goto error; |
797 | 798 | } |
798 | 799 | |
799 | 800 | key_ref = ERR_PTR(-EINVAL); |
800 | - if (!ktype->match || !ktype->instantiate || | |
801 | - (!description && !ktype->preparse)) | |
801 | + if (!index_key.type->match || !index_key.type->instantiate || | |
802 | + (!index_key.description && !index_key.type->preparse)) | |
802 | 803 | goto error_put_type; |
803 | 804 | |
804 | 805 | keyring = key_ref_to_ptr(keyring_ref); |
805 | 806 | |
806 | 807 | |
807 | 808 | |
808 | 809 | |
... | ... | @@ -812,21 +813,22 @@ |
812 | 813 | memset(&prep, 0, sizeof(prep)); |
813 | 814 | prep.data = payload; |
814 | 815 | prep.datalen = plen; |
815 | - prep.quotalen = ktype->def_datalen; | |
816 | - if (ktype->preparse) { | |
817 | - ret = ktype->preparse(&prep); | |
816 | + prep.quotalen = index_key.type->def_datalen; | |
817 | + if (index_key.type->preparse) { | |
818 | + ret = index_key.type->preparse(&prep); | |
818 | 819 | if (ret < 0) { |
819 | 820 | key_ref = ERR_PTR(ret); |
820 | 821 | goto error_put_type; |
821 | 822 | } |
822 | - if (!description) | |
823 | - description = prep.description; | |
823 | + if (!index_key.description) | |
824 | + index_key.description = prep.description; | |
824 | 825 | key_ref = ERR_PTR(-EINVAL); |
825 | - if (!description) | |
826 | + if (!index_key.description) | |
826 | 827 | goto error_free_prep; |
827 | 828 | } |
829 | + index_key.desc_len = strlen(index_key.description); | |
828 | 830 | |
829 | - ret = __key_link_begin(keyring, ktype, description, &prealloc); | |
831 | + ret = __key_link_begin(keyring, &index_key, &prealloc); | |
830 | 832 | if (ret < 0) { |
831 | 833 | key_ref = ERR_PTR(ret); |
832 | 834 | goto error_free_prep; |
... | ... | @@ -844,9 +846,8 @@ |
844 | 846 | * key of the same type and description in the destination keyring and |
845 | 847 | * update that instead if possible |
846 | 848 | */ |
847 | - if (ktype->update) { | |
848 | - key_ref = __keyring_search_one(keyring_ref, ktype, description, | |
849 | - 0); | |
849 | + if (index_key.type->update) { | |
850 | + key_ref = __keyring_search_one(keyring_ref, &index_key, 0); | |
850 | 851 | if (!IS_ERR(key_ref)) |
851 | 852 | goto found_matching_key; |
852 | 853 | } |
853 | 854 | |
854 | 855 | |
... | ... | @@ -856,16 +857,17 @@ |
856 | 857 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
857 | 858 | perm |= KEY_USR_VIEW; |
858 | 859 | |
859 | - if (ktype->read) | |
860 | + if (index_key.type->read) | |
860 | 861 | perm |= KEY_POS_READ; |
861 | 862 | |
862 | - if (ktype == &key_type_keyring || ktype->update) | |
863 | + if (index_key.type == &key_type_keyring || | |
864 | + index_key.type->update) | |
863 | 865 | perm |= KEY_POS_WRITE; |
864 | 866 | } |
865 | 867 | |
866 | 868 | /* allocate a new key */ |
867 | - key = key_alloc(ktype, description, cred->fsuid, cred->fsgid, cred, | |
868 | - perm, flags); | |
869 | + key = key_alloc(index_key.type, index_key.description, | |
870 | + cred->fsuid, cred->fsgid, cred, perm, flags); | |
869 | 871 | if (IS_ERR(key)) { |
870 | 872 | key_ref = ERR_CAST(key); |
871 | 873 | goto error_link_end; |
872 | 874 | |
873 | 875 | |
... | ... | @@ -882,12 +884,12 @@ |
882 | 884 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
883 | 885 | |
884 | 886 | error_link_end: |
885 | - __key_link_end(keyring, ktype, prealloc); | |
887 | + __key_link_end(keyring, &index_key, prealloc); | |
886 | 888 | error_free_prep: |
887 | - if (ktype->preparse) | |
888 | - ktype->free_preparse(&prep); | |
889 | + if (index_key.type->preparse) | |
890 | + index_key.type->free_preparse(&prep); | |
889 | 891 | error_put_type: |
890 | - key_type_put(ktype); | |
892 | + key_type_put(index_key.type); | |
891 | 893 | error: |
892 | 894 | return key_ref; |
893 | 895 | |
... | ... | @@ -895,7 +897,7 @@ |
895 | 897 | /* we found a matching key, so we're going to try to update it |
896 | 898 | * - we can drop the locks first as we have the key pinned |
897 | 899 | */ |
898 | - __key_link_end(keyring, ktype, prealloc); | |
900 | + __key_link_end(keyring, &index_key, prealloc); | |
899 | 901 | |
900 | 902 | key_ref = __key_update(key_ref, &prep); |
901 | 903 | goto error_free_prep; |
security/keys/keyring.c
... | ... | @@ -538,8 +538,7 @@ |
538 | 538 | * to the returned key reference. |
539 | 539 | */ |
540 | 540 | key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
541 | - const struct key_type *ktype, | |
542 | - const char *description, | |
541 | + const struct keyring_index_key *index_key, | |
543 | 542 | key_perm_t perm) |
544 | 543 | { |
545 | 544 | struct keyring_list *klist; |
546 | 545 | |
... | ... | @@ -558,9 +557,9 @@ |
558 | 557 | smp_rmb(); |
559 | 558 | for (loop = 0; loop < nkeys ; loop++) { |
560 | 559 | key = rcu_dereference(klist->keys[loop]); |
561 | - if (key->type == ktype && | |
560 | + if (key->type == index_key->type && | |
562 | 561 | (!key->type->match || |
563 | - key->type->match(key, description)) && | |
562 | + key->type->match(key, index_key->description)) && | |
564 | 563 | key_permission(make_key_ref(key, possessed), |
565 | 564 | perm) == 0 && |
566 | 565 | !(key->flags & ((1 << KEY_FLAG_INVALIDATED) | |
... | ... | @@ -747,8 +746,8 @@ |
747 | 746 | /* |
748 | 747 | * Preallocate memory so that a key can be linked into to a keyring. |
749 | 748 | */ |
750 | -int __key_link_begin(struct key *keyring, const struct key_type *type, | |
751 | - const char *description, unsigned long *_prealloc) | |
749 | +int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key, | |
750 | + unsigned long *_prealloc) | |
752 | 751 | __acquires(&keyring->sem) |
753 | 752 | __acquires(&keyring_serialise_link_sem) |
754 | 753 | { |
... | ... | @@ -759,7 +758,8 @@ |
759 | 758 | size_t size; |
760 | 759 | int loop, lru, ret; |
761 | 760 | |
762 | - kenter("%d,%s,%s,", key_serial(keyring), type->name, description); | |
761 | + kenter("%d,%s,%s,", | |
762 | + key_serial(keyring), index_key->type->name, index_key->description); | |
763 | 763 | |
764 | 764 | if (keyring->type != &key_type_keyring) |
765 | 765 | return -ENOTDIR; |
... | ... | @@ -772,7 +772,7 @@ |
772 | 772 | |
773 | 773 | /* serialise link/link calls to prevent parallel calls causing a cycle |
774 | 774 | * when linking two keyring in opposite orders */ |
775 | - if (type == &key_type_keyring) | |
775 | + if (index_key->type == &key_type_keyring) | |
776 | 776 | down_write(&keyring_serialise_link_sem); |
777 | 777 | |
778 | 778 | klist = rcu_dereference_locked_keyring(keyring); |
... | ... | @@ -784,8 +784,8 @@ |
784 | 784 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
785 | 785 | struct key *key = rcu_deref_link_locked(klist, loop, |
786 | 786 | keyring); |
787 | - if (key->type == type && | |
788 | - strcmp(key->description, description) == 0) { | |
787 | + if (key->type == index_key->type && | |
788 | + strcmp(key->description, index_key->description) == 0) { | |
789 | 789 | /* Found a match - we'll replace the link with |
790 | 790 | * one to the new key. We record the slot |
791 | 791 | * position. |
... | ... | @@ -865,7 +865,7 @@ |
865 | 865 | key_payload_reserve(keyring, |
866 | 866 | keyring->datalen - KEYQUOTA_LINK_BYTES); |
867 | 867 | error_sem: |
868 | - if (type == &key_type_keyring) | |
868 | + if (index_key->type == &key_type_keyring) | |
869 | 869 | up_write(&keyring_serialise_link_sem); |
870 | 870 | error_krsem: |
871 | 871 | up_write(&keyring->sem); |
872 | 872 | |
873 | 873 | |
... | ... | @@ -957,16 +957,17 @@ |
957 | 957 | * |
958 | 958 | * Must be called with __key_link_begin() having being called. |
959 | 959 | */ |
960 | -void __key_link_end(struct key *keyring, struct key_type *type, | |
960 | +void __key_link_end(struct key *keyring, | |
961 | + const struct keyring_index_key *index_key, | |
961 | 962 | unsigned long prealloc) |
962 | 963 | __releases(&keyring->sem) |
963 | 964 | __releases(&keyring_serialise_link_sem) |
964 | 965 | { |
965 | - BUG_ON(type == NULL); | |
966 | - BUG_ON(type->name == NULL); | |
967 | - kenter("%d,%s,%lx", keyring->serial, type->name, prealloc); | |
966 | + BUG_ON(index_key->type == NULL); | |
967 | + BUG_ON(index_key->type->name == NULL); | |
968 | + kenter("%d,%s,%lx", keyring->serial, index_key->type->name, prealloc); | |
968 | 969 | |
969 | - if (type == &key_type_keyring) | |
970 | + if (index_key->type == &key_type_keyring) | |
970 | 971 | up_write(&keyring_serialise_link_sem); |
971 | 972 | |
972 | 973 | if (prealloc) { |
973 | 974 | |
... | ... | @@ -1007,12 +1008,12 @@ |
1007 | 1008 | key_check(keyring); |
1008 | 1009 | key_check(key); |
1009 | 1010 | |
1010 | - ret = __key_link_begin(keyring, key->type, key->description, &prealloc); | |
1011 | + ret = __key_link_begin(keyring, &key->index_key, &prealloc); | |
1011 | 1012 | if (ret == 0) { |
1012 | 1013 | ret = __key_link_check_live_key(keyring, key); |
1013 | 1014 | if (ret == 0) |
1014 | 1015 | __key_link(keyring, key, &prealloc); |
1015 | - __key_link_end(keyring, key->type, prealloc); | |
1016 | + __key_link_end(keyring, &key->index_key, prealloc); | |
1016 | 1017 | } |
1017 | 1018 | |
1018 | 1019 | return ret; |
security/keys/request_key.c
... | ... | @@ -352,6 +352,11 @@ |
352 | 352 | struct key_user *user, |
353 | 353 | struct key **_key) |
354 | 354 | { |
355 | + const struct keyring_index_key index_key = { | |
356 | + .type = type, | |
357 | + .description = description, | |
358 | + .desc_len = strlen(description), | |
359 | + }; | |
355 | 360 | const struct cred *cred = current_cred(); |
356 | 361 | unsigned long prealloc; |
357 | 362 | struct key *key; |
... | ... | @@ -379,8 +384,7 @@ |
379 | 384 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
380 | 385 | |
381 | 386 | if (dest_keyring) { |
382 | - ret = __key_link_begin(dest_keyring, type, description, | |
383 | - &prealloc); | |
387 | + ret = __key_link_begin(dest_keyring, &index_key, &prealloc); | |
384 | 388 | if (ret < 0) |
385 | 389 | goto link_prealloc_failed; |
386 | 390 | } |
... | ... | @@ -400,7 +404,7 @@ |
400 | 404 | |
401 | 405 | mutex_unlock(&key_construction_mutex); |
402 | 406 | if (dest_keyring) |
403 | - __key_link_end(dest_keyring, type, prealloc); | |
407 | + __key_link_end(dest_keyring, &index_key, prealloc); | |
404 | 408 | mutex_unlock(&user->cons_lock); |
405 | 409 | *_key = key; |
406 | 410 | kleave(" = 0 [%d]", key_serial(key)); |
... | ... | @@ -416,7 +420,7 @@ |
416 | 420 | ret = __key_link_check_live_key(dest_keyring, key); |
417 | 421 | if (ret == 0) |
418 | 422 | __key_link(dest_keyring, key, &prealloc); |
419 | - __key_link_end(dest_keyring, type, prealloc); | |
423 | + __key_link_end(dest_keyring, &index_key, prealloc); | |
420 | 424 | if (ret < 0) |
421 | 425 | goto link_check_failed; |
422 | 426 | } |