Commit 16feef4340172b7dbb9cba60850e78fa6388adf1

Authored by David Howells
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

... ... @@ -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,
... ... @@ -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 }