summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c31
-rw-r--r--include/keys/user-type.h4
-rw-r--r--include/linux/key-type.h31
-rw-r--r--net/dns_resolver/dns_key.c5
-rw-r--r--security/keys/internal.h8
-rw-r--r--security/keys/keyring.c49
-rw-r--r--security/keys/proc.c8
-rw-r--r--security/keys/process_keys.c13
-rw-r--r--security/keys/request_key.c21
-rw-r--r--security/keys/request_key_auth.c6
-rw-r--r--security/keys/user_defined.c4
11 files changed, 129 insertions, 51 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index eb8cd46961a5..f666b4e8d256 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -59,9 +59,11 @@ EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
59 * "id:<id>" - request a key matching the ID 59 * "id:<id>" - request a key matching the ID
60 * "<subtype>:<id>" - request a key of a subtype 60 * "<subtype>:<id>" - request a key of a subtype
61 */ 61 */
62static int asymmetric_key_match(const struct key *key, const void *description) 62static int asymmetric_key_match(const struct key *key,
63 const struct key_match_data *match_data)
63{ 64{
64 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); 65 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
66 const char *description = match_data->raw_data;
65 const char *spec = description; 67 const char *spec = description;
66 const char *id; 68 const char *id;
67 ptrdiff_t speclen; 69 ptrdiff_t speclen;
@@ -94,6 +96,31 @@ static int asymmetric_key_match(const struct key *key, const void *description)
94} 96}
95 97
96/* 98/*
99 * Preparse the match criterion. If we don't set lookup_type and cmp,
100 * the default will be an exact match on the key description.
101 *
102 * There are some specifiers for matching key IDs rather than by the key
103 * description:
104 *
105 * "id:<id>" - request a key by any available ID
106 *
107 * These have to be searched by iteration rather than by direct lookup because
108 * the key is hashed according to its description.
109 */
110static int asymmetric_key_match_preparse(struct key_match_data *match_data)
111{
112 match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
113 return 0;
114}
115
116/*
117 * Free the preparsed the match criterion.
118 */
119static void asymmetric_key_match_free(struct key_match_data *match_data)
120{
121}
122
123/*
97 * Describe the asymmetric key 124 * Describe the asymmetric key
98 */ 125 */
99static void asymmetric_key_describe(const struct key *key, struct seq_file *m) 126static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
@@ -196,7 +223,9 @@ struct key_type key_type_asymmetric = {
196 .preparse = asymmetric_key_preparse, 223 .preparse = asymmetric_key_preparse,
197 .free_preparse = asymmetric_key_free_preparse, 224 .free_preparse = asymmetric_key_free_preparse,
198 .instantiate = generic_key_instantiate, 225 .instantiate = generic_key_instantiate,
226 .match_preparse = asymmetric_key_match_preparse,
199 .match = asymmetric_key_match, 227 .match = asymmetric_key_match,
228 .match_free = asymmetric_key_match_free,
200 .destroy = asymmetric_key_destroy, 229 .destroy = asymmetric_key_destroy,
201 .describe = asymmetric_key_describe, 230 .describe = asymmetric_key_describe,
202 .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE, 231 .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 3ab1873a4bfa..66d92af30e7c 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -36,11 +36,13 @@ extern struct key_type key_type_user;
36extern struct key_type key_type_logon; 36extern struct key_type key_type_logon;
37 37
38struct key_preparsed_payload; 38struct key_preparsed_payload;
39struct key_match_data;
39 40
40extern int user_preparse(struct key_preparsed_payload *prep); 41extern int user_preparse(struct key_preparsed_payload *prep);
41extern void user_free_preparse(struct key_preparsed_payload *prep); 42extern void user_free_preparse(struct key_preparsed_payload *prep);
42extern int user_update(struct key *key, struct key_preparsed_payload *prep); 43extern int user_update(struct key *key, struct key_preparsed_payload *prep);
43extern int user_match(const struct key *key, const void *criterion); 44extern int user_match(const struct key *key,
45 const struct key_match_data *match_data);
44extern void user_revoke(struct key *key); 46extern void user_revoke(struct key *key);
45extern void user_destroy(struct key *key); 47extern void user_destroy(struct key *key);
46extern void user_describe(const struct key *user, struct seq_file *m); 48extern void user_describe(const struct key *user, struct seq_file *m);
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 44792ee649de..8aba688a451a 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -53,6 +53,22 @@ typedef int (*request_key_actor_t)(struct key_construction *key,
53 const char *op, void *aux); 53 const char *op, void *aux);
54 54
55/* 55/*
56 * Preparsed matching criterion.
57 */
58struct key_match_data {
59 /* Comparison function, defaults to type->match, but can be replaced by
60 * type->match_preparse(). */
61 int (*cmp)(const struct key *key,
62 const struct key_match_data *match_data);
63
64 const void *raw_data; /* Raw match data */
65 void *preparsed; /* For ->match_preparse() to stash stuff */
66 unsigned lookup_type; /* Type of lookup for this search. */
67#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */
68#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */
69};
70
71/*
56 * kernel managed key type definition 72 * kernel managed key type definition
57 */ 73 */
58struct key_type { 74struct key_type {
@@ -67,8 +83,6 @@ struct key_type {
67 83
68 /* Default key search algorithm. */ 84 /* Default key search algorithm. */
69 unsigned def_lookup_type; 85 unsigned def_lookup_type;
70#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */
71#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */
72 86
73 /* vet a description */ 87 /* vet a description */
74 int (*vet_description)(const char *description); 88 int (*vet_description)(const char *description);
@@ -96,8 +110,19 @@ struct key_type {
96 */ 110 */
97 int (*update)(struct key *key, struct key_preparsed_payload *prep); 111 int (*update)(struct key *key, struct key_preparsed_payload *prep);
98 112
113 /* Preparse the data supplied to ->match() (optional). The
114 * data to be preparsed can be found in match_data->raw_data.
115 * The lookup type can also be set by this function.
116 */
117 int (*match_preparse)(struct key_match_data *match_data);
118
99 /* match a key against a description */ 119 /* match a key against a description */
100 int (*match)(const struct key *key, const void *desc); 120 int (*match)(const struct key *key,
121 const struct key_match_data *match_data);
122
123 /* Free preparsed match data (optional). This should be supplied it
124 * ->match_preparse() is supplied. */
125 void (*match_free)(struct key_match_data *match_data);
101 126
102 /* clear some of the data from a key on revokation (optional) 127 /* clear some of the data from a key on revokation (optional)
103 * - the key's semaphore will be write-locked by the caller 128 * - the key's semaphore will be write-locked by the caller
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index f380b2c58178..92df6e508ae7 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -177,10 +177,11 @@ static void dns_resolver_free_preparse(struct key_preparsed_payload *prep)
177 * should end with a period). The domain name is case-independent. 177 * should end with a period). The domain name is case-independent.
178 */ 178 */
179static int 179static int
180dns_resolver_match(const struct key *key, const void *description) 180dns_resolver_match(const struct key *key,
181 const struct key_match_data *match_data)
181{ 182{
182 int slen, dlen, ret = 0; 183 int slen, dlen, ret = 0;
183 const char *src = key->description, *dsp = description; 184 const char *src = key->description, *dsp = match_data->raw_data;
184 185
185 kenter("%s,%s", src, dsp); 186 kenter("%s,%s", src, dsp);
186 187
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 5f20da01fd8d..805e60b0b87e 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -107,13 +107,10 @@ extern int iterate_over_keyring(const struct key *keyring,
107 int (*func)(const struct key *key, void *data), 107 int (*func)(const struct key *key, void *data),
108 void *data); 108 void *data);
109 109
110typedef int (*key_match_func_t)(const struct key *, const void *);
111
112struct keyring_search_context { 110struct keyring_search_context {
113 struct keyring_index_key index_key; 111 struct keyring_index_key index_key;
114 const struct cred *cred; 112 const struct cred *cred;
115 key_match_func_t match; 113 struct key_match_data match_data;
116 const void *match_data;
117 unsigned flags; 114 unsigned flags;
118#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ 115#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */
119#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ 116#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */
@@ -152,7 +149,8 @@ extern struct key *request_key_and_link(struct key_type *type,
152 struct key *dest_keyring, 149 struct key *dest_keyring,
153 unsigned long flags); 150 unsigned long flags);
154 151
155extern int lookup_user_key_possessed(const struct key *key, const void *target); 152extern int lookup_user_key_possessed(const struct key *key,
153 const struct key_match_data *match_data);
156extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, 154extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
157 key_perm_t perm); 155 key_perm_t perm);
158#define KEY_LOOKUP_CREATE 0x01 156#define KEY_LOOKUP_CREATE 0x01
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 8314a7d2104d..10f0a5f2d362 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -545,7 +545,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
545 } 545 }
546 546
547 /* keys that don't match */ 547 /* keys that don't match */
548 if (!ctx->match(key, ctx->match_data)) { 548 if (!ctx->match_data.cmp(key, &ctx->match_data)) {
549 kleave(" = 0 [!match]"); 549 kleave(" = 0 [!match]");
550 return 0; 550 return 0;
551 } 551 }
@@ -585,8 +585,7 @@ skipped:
585 */ 585 */
586static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) 586static int search_keyring(struct key *keyring, struct keyring_search_context *ctx)
587{ 587{
588 if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == 588 if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) {
589 KEYRING_SEARCH_LOOKUP_DIRECT) {
590 const void *object; 589 const void *object;
591 590
592 object = assoc_array_find(&keyring->keys, 591 object = assoc_array_find(&keyring->keys,
@@ -627,7 +626,7 @@ static bool search_nested_keyrings(struct key *keyring,
627 /* Check to see if this top-level keyring is what we are looking for 626 /* Check to see if this top-level keyring is what we are looking for
628 * and whether it is valid or not. 627 * and whether it is valid or not.
629 */ 628 */
630 if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE || 629 if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_ITERATE ||
631 keyring_compare_object(keyring, &ctx->index_key)) { 630 keyring_compare_object(keyring, &ctx->index_key)) {
632 ctx->skipped_ret = 2; 631 ctx->skipped_ret = 2;
633 ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; 632 ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK;
@@ -885,16 +884,28 @@ key_ref_t keyring_search(key_ref_t keyring,
885 .index_key.type = type, 884 .index_key.type = type,
886 .index_key.description = description, 885 .index_key.description = description,
887 .cred = current_cred(), 886 .cred = current_cred(),
888 .match = type->match, 887 .match_data.cmp = type->match,
889 .match_data = description, 888 .match_data.raw_data = description,
890 .flags = (type->def_lookup_type | 889 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
891 KEYRING_SEARCH_DO_STATE_CHECK), 890 .flags = KEYRING_SEARCH_DO_STATE_CHECK,
892 }; 891 };
892 key_ref_t key;
893 int ret;
893 894
894 if (!ctx.match) 895 if (!ctx.match_data.cmp)
895 return ERR_PTR(-ENOKEY); 896 return ERR_PTR(-ENOKEY);
896 897
897 return keyring_search_aux(keyring, &ctx); 898 if (type->match_preparse) {
899 ret = type->match_preparse(&ctx.match_data);
900 if (ret < 0)
901 return ERR_PTR(ret);
902 }
903
904 key = keyring_search_aux(keyring, &ctx);
905
906 if (type->match_free)
907 type->match_free(&ctx.match_data);
908 return key;
898} 909}
899EXPORT_SYMBOL(keyring_search); 910EXPORT_SYMBOL(keyring_search);
900 911
@@ -1014,7 +1025,7 @@ static int keyring_detect_cycle_iterator(const void *object,
1014 1025
1015 /* We might get a keyring with matching index-key that is nonetheless a 1026 /* We might get a keyring with matching index-key that is nonetheless a
1016 * different keyring. */ 1027 * different keyring. */
1017 if (key != ctx->match_data) 1028 if (key != ctx->match_data.raw_data)
1018 return 0; 1029 return 0;
1019 1030
1020 ctx->result = ERR_PTR(-EDEADLK); 1031 ctx->result = ERR_PTR(-EDEADLK);
@@ -1031,14 +1042,14 @@ static int keyring_detect_cycle_iterator(const void *object,
1031static int keyring_detect_cycle(struct key *A, struct key *B) 1042static int keyring_detect_cycle(struct key *A, struct key *B)
1032{ 1043{
1033 struct keyring_search_context ctx = { 1044 struct keyring_search_context ctx = {
1034 .index_key = A->index_key, 1045 .index_key = A->index_key,
1035 .match_data = A, 1046 .match_data.raw_data = A,
1036 .iterator = keyring_detect_cycle_iterator, 1047 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
1037 .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | 1048 .iterator = keyring_detect_cycle_iterator,
1038 KEYRING_SEARCH_NO_STATE_CHECK | 1049 .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
1039 KEYRING_SEARCH_NO_UPDATE_TIME | 1050 KEYRING_SEARCH_NO_UPDATE_TIME |
1040 KEYRING_SEARCH_NO_CHECK_PERM | 1051 KEYRING_SEARCH_NO_CHECK_PERM |
1041 KEYRING_SEARCH_DETECT_TOO_DEEP), 1052 KEYRING_SEARCH_DETECT_TOO_DEEP),
1042 }; 1053 };
1043 1054
1044 rcu_read_lock(); 1055 rcu_read_lock();
diff --git a/security/keys/proc.c b/security/keys/proc.c
index d3f6f2fd21db..972eeb336b81 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -194,10 +194,10 @@ static int proc_keys_show(struct seq_file *m, void *v)
194 .index_key.type = key->type, 194 .index_key.type = key->type,
195 .index_key.description = key->description, 195 .index_key.description = key->description,
196 .cred = current_cred(), 196 .cred = current_cred(),
197 .match = lookup_user_key_possessed, 197 .match_data.cmp = lookup_user_key_possessed,
198 .match_data = key, 198 .match_data.raw_data = key,
199 .flags = (KEYRING_SEARCH_NO_STATE_CHECK | 199 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
200 KEYRING_SEARCH_LOOKUP_DIRECT), 200 .flags = KEYRING_SEARCH_NO_STATE_CHECK,
201 }; 201 };
202 202
203 key_ref = make_key_ref(key, 0); 203 key_ref = make_key_ref(key, 0);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 0cf8a130a267..08bd533d014f 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -489,9 +489,10 @@ found:
489/* 489/*
490 * See if the key we're looking at is the target key. 490 * See if the key we're looking at is the target key.
491 */ 491 */
492int lookup_user_key_possessed(const struct key *key, const void *target) 492int lookup_user_key_possessed(const struct key *key,
493 const struct key_match_data *match_data)
493{ 494{
494 return key == target; 495 return key == match_data->raw_data;
495} 496}
496 497
497/* 498/*
@@ -516,9 +517,9 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
516 key_perm_t perm) 517 key_perm_t perm)
517{ 518{
518 struct keyring_search_context ctx = { 519 struct keyring_search_context ctx = {
519 .match = lookup_user_key_possessed, 520 .match_data.cmp = lookup_user_key_possessed,
520 .flags = (KEYRING_SEARCH_NO_STATE_CHECK | 521 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
521 KEYRING_SEARCH_LOOKUP_DIRECT), 522 .flags = KEYRING_SEARCH_NO_STATE_CHECK,
522 }; 523 };
523 struct request_key_auth *rka; 524 struct request_key_auth *rka;
524 struct key *key; 525 struct key *key;
@@ -673,7 +674,7 @@ try_again:
673 ctx.index_key.type = key->type; 674 ctx.index_key.type = key->type;
674 ctx.index_key.description = key->description; 675 ctx.index_key.description = key->description;
675 ctx.index_key.desc_len = strlen(key->description); 676 ctx.index_key.desc_len = strlen(key->description);
676 ctx.match_data = key; 677 ctx.match_data.raw_data = key;
677 kdebug("check possessed"); 678 kdebug("check possessed");
678 skey_ref = search_process_keyrings(&ctx); 679 skey_ref = search_process_keyrings(&ctx);
679 kdebug("possessed=%p", skey_ref); 680 kdebug("possessed=%p", skey_ref);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 381411941cc1..408523e5e2e2 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -531,9 +531,9 @@ struct key *request_key_and_link(struct key_type *type,
531 .index_key.type = type, 531 .index_key.type = type,
532 .index_key.description = description, 532 .index_key.description = description,
533 .cred = current_cred(), 533 .cred = current_cred(),
534 .match = type->match, 534 .match_data.cmp = type->match,
535 .match_data = description, 535 .match_data.raw_data = description,
536 .flags = KEYRING_SEARCH_LOOKUP_DIRECT, 536 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
537 }; 537 };
538 struct key *key; 538 struct key *key;
539 key_ref_t key_ref; 539 key_ref_t key_ref;
@@ -543,6 +543,14 @@ struct key *request_key_and_link(struct key_type *type,
543 ctx.index_key.type->name, ctx.index_key.description, 543 ctx.index_key.type->name, ctx.index_key.description,
544 callout_info, callout_len, aux, dest_keyring, flags); 544 callout_info, callout_len, aux, dest_keyring, flags);
545 545
546 if (type->match_preparse) {
547 ret = type->match_preparse(&ctx.match_data);
548 if (ret < 0) {
549 key = ERR_PTR(ret);
550 goto error;
551 }
552 }
553
546 /* search all the process keyrings for a key */ 554 /* search all the process keyrings for a key */
547 key_ref = search_process_keyrings(&ctx); 555 key_ref = search_process_keyrings(&ctx);
548 556
@@ -555,7 +563,7 @@ struct key *request_key_and_link(struct key_type *type,
555 if (ret < 0) { 563 if (ret < 0) {
556 key_put(key); 564 key_put(key);
557 key = ERR_PTR(ret); 565 key = ERR_PTR(ret);
558 goto error; 566 goto error_free;
559 } 567 }
560 } 568 }
561 } else if (PTR_ERR(key_ref) != -EAGAIN) { 569 } else if (PTR_ERR(key_ref) != -EAGAIN) {
@@ -565,12 +573,15 @@ struct key *request_key_and_link(struct key_type *type,
565 * should consult userspace if we can */ 573 * should consult userspace if we can */
566 key = ERR_PTR(-ENOKEY); 574 key = ERR_PTR(-ENOKEY);
567 if (!callout_info) 575 if (!callout_info)
568 goto error; 576 goto error_free;
569 577
570 key = construct_key_and_link(&ctx, callout_info, callout_len, 578 key = construct_key_and_link(&ctx, callout_info, callout_len,
571 aux, dest_keyring, flags); 579 aux, dest_keyring, flags);
572 } 580 }
573 581
582error_free:
583 if (type->match_free)
584 type->match_free(&ctx.match_data);
574error: 585error:
575 kleave(" = %p", key); 586 kleave(" = %p", key);
576 return key; 587 return key;
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 739e7455d388..9ae02819cc06 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -246,9 +246,9 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
246 .index_key.type = &key_type_request_key_auth, 246 .index_key.type = &key_type_request_key_auth,
247 .index_key.description = description, 247 .index_key.description = description,
248 .cred = current_cred(), 248 .cred = current_cred(),
249 .match = user_match, 249 .match_data.cmp = user_match,
250 .match_data = description, 250 .match_data.raw_data = description,
251 .flags = KEYRING_SEARCH_LOOKUP_DIRECT, 251 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
252 }; 252 };
253 struct key *authkey; 253 struct key *authkey;
254 key_ref_t authkey_ref; 254 key_ref_t authkey_ref;
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index eee340011f2b..ec8a56063b02 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -141,9 +141,9 @@ EXPORT_SYMBOL_GPL(user_update);
141/* 141/*
142 * match users on their name 142 * match users on their name
143 */ 143 */
144int user_match(const struct key *key, const void *description) 144int user_match(const struct key *key, const struct key_match_data *match_data)
145{ 145{
146 return strcmp(key->description, description) == 0; 146 return strcmp(key->description, match_data->raw_data) == 0;
147} 147}
148 148
149EXPORT_SYMBOL_GPL(user_match); 149EXPORT_SYMBOL_GPL(user_match);