diff options
author | David Howells <dhowells@redhat.com> | 2019-06-26 16:02:32 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-06-26 16:02:32 -0400 |
commit | dcf49dbc8077e278ddd1bc7298abc781496e8a08 (patch) | |
tree | e187765e6336fefc35d83f5b75b7cbe1d4ec194a | |
parent | 355ef8e15885020da88f5ba2d85ce42b1d01f537 (diff) |
keys: Add a 'recurse' flag for keyring searches
Add a 'recurse' flag for keyring searches so that the flag can be omitted
and recursion disabled, thereby allowing just the nominated keyring to be
searched and none of the children.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | Documentation/security/keys/core.rst | 10 | ||||
-rw-r--r-- | certs/blacklist.c | 2 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 2 | ||||
-rw-r--r-- | include/linux/key.h | 3 | ||||
-rw-r--r-- | lib/digsig.c | 2 | ||||
-rw-r--r-- | net/rxrpc/security.c | 2 | ||||
-rw-r--r-- | security/integrity/digsig_asymmetric.c | 4 | ||||
-rw-r--r-- | security/keys/internal.h | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 | ||||
-rw-r--r-- | security/keys/keyring.c | 12 | ||||
-rw-r--r-- | security/keys/proc.c | 3 | ||||
-rw-r--r-- | security/keys/process_keys.c | 3 | ||||
-rw-r--r-- | security/keys/request_key.c | 3 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 3 |
14 files changed, 34 insertions, 18 deletions
diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst index a0e245f9576f..ae930ae9d590 100644 --- a/Documentation/security/keys/core.rst +++ b/Documentation/security/keys/core.rst | |||
@@ -1162,11 +1162,13 @@ payload contents" for more information. | |||
1162 | 1162 | ||
1163 | key_ref_t keyring_search(key_ref_t keyring_ref, | 1163 | key_ref_t keyring_search(key_ref_t keyring_ref, |
1164 | const struct key_type *type, | 1164 | const struct key_type *type, |
1165 | const char *description) | 1165 | const char *description, |
1166 | bool recurse) | ||
1166 | 1167 | ||
1167 | This searches the keyring tree specified for a matching key. Error ENOKEY | 1168 | This searches the specified keyring only (recurse == false) or keyring tree |
1168 | is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful, | 1169 | (recurse == true) specified for a matching key. Error ENOKEY is returned |
1169 | the returned key will need to be released. | 1170 | upon failure (use IS_ERR/PTR_ERR to determine). If successful, the returned |
1171 | key will need to be released. | ||
1170 | 1172 | ||
1171 | The possession attribute from the keyring reference is used to control | 1173 | The possession attribute from the keyring reference is used to control |
1172 | access through the permissions mask and is propagated to the returned key | 1174 | access through the permissions mask and is propagated to the returned key |
diff --git a/certs/blacklist.c b/certs/blacklist.c index 3a507b9e2568..181cb7fa9540 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c | |||
@@ -128,7 +128,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type) | |||
128 | *p = 0; | 128 | *p = 0; |
129 | 129 | ||
130 | kref = keyring_search(make_key_ref(blacklist_keyring, true), | 130 | kref = keyring_search(make_key_ref(blacklist_keyring, true), |
131 | &key_type_blacklist, buffer); | 131 | &key_type_blacklist, buffer, false); |
132 | if (!IS_ERR(kref)) { | 132 | if (!IS_ERR(kref)) { |
133 | key_ref_put(kref); | 133 | key_ref_put(kref); |
134 | ret = -EKEYREJECTED; | 134 | ret = -EKEYREJECTED; |
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 69a0788a7de5..084027ef3121 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c | |||
@@ -87,7 +87,7 @@ struct key *find_asymmetric_key(struct key *keyring, | |||
87 | pr_debug("Look up: \"%s\"\n", req); | 87 | pr_debug("Look up: \"%s\"\n", req); |
88 | 88 | ||
89 | ref = keyring_search(make_key_ref(keyring, 1), | 89 | ref = keyring_search(make_key_ref(keyring, 1), |
90 | &key_type_asymmetric, req); | 90 | &key_type_asymmetric, req, true); |
91 | if (IS_ERR(ref)) | 91 | if (IS_ERR(ref)) |
92 | pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); | 92 | pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); |
93 | kfree(req); | 93 | kfree(req); |
diff --git a/include/linux/key.h b/include/linux/key.h index fb2debcacea0..ff102731b3db 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -341,7 +341,8 @@ extern int keyring_clear(struct key *keyring); | |||
341 | 341 | ||
342 | extern key_ref_t keyring_search(key_ref_t keyring, | 342 | extern key_ref_t keyring_search(key_ref_t keyring, |
343 | struct key_type *type, | 343 | struct key_type *type, |
344 | const char *description); | 344 | const char *description, |
345 | bool recurse); | ||
345 | 346 | ||
346 | extern int keyring_add_key(struct key *keyring, | 347 | extern int keyring_add_key(struct key *keyring, |
347 | struct key *key); | 348 | struct key *key); |
diff --git a/lib/digsig.c b/lib/digsig.c index 3b0a579bdcdf..3782af401c68 100644 --- a/lib/digsig.c +++ b/lib/digsig.c | |||
@@ -221,7 +221,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen, | |||
221 | /* search in specific keyring */ | 221 | /* search in specific keyring */ |
222 | key_ref_t kref; | 222 | key_ref_t kref; |
223 | kref = keyring_search(make_key_ref(keyring, 1UL), | 223 | kref = keyring_search(make_key_ref(keyring, 1UL), |
224 | &key_type_user, name); | 224 | &key_type_user, name, true); |
225 | if (IS_ERR(kref)) | 225 | if (IS_ERR(kref)) |
226 | key = ERR_CAST(kref); | 226 | key = ERR_CAST(kref); |
227 | else | 227 | else |
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c index c4479afe8ae7..2cfc7125bc41 100644 --- a/net/rxrpc/security.c +++ b/net/rxrpc/security.c | |||
@@ -148,7 +148,7 @@ found_service: | |||
148 | 148 | ||
149 | /* look through the service's keyring */ | 149 | /* look through the service's keyring */ |
150 | kref = keyring_search(make_key_ref(rx->securities, 1UL), | 150 | kref = keyring_search(make_key_ref(rx->securities, 1UL), |
151 | &key_type_rxrpc_s, kdesc); | 151 | &key_type_rxrpc_s, kdesc, true); |
152 | if (IS_ERR(kref)) { | 152 | if (IS_ERR(kref)) { |
153 | read_unlock(&local->services_lock); | 153 | read_unlock(&local->services_lock); |
154 | _leave(" = %ld [search]", PTR_ERR(kref)); | 154 | _leave(" = %ld [search]", PTR_ERR(kref)); |
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 99080871eb9f..358f614811e8 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c | |||
@@ -39,7 +39,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
39 | key_ref_t kref; | 39 | key_ref_t kref; |
40 | 40 | ||
41 | kref = keyring_search(make_key_ref(key, 1), | 41 | kref = keyring_search(make_key_ref(key, 1), |
42 | &key_type_asymmetric, name); | 42 | &key_type_asymmetric, name, true); |
43 | if (!IS_ERR(kref)) { | 43 | if (!IS_ERR(kref)) { |
44 | pr_err("Key '%s' is in ima_blacklist_keyring\n", name); | 44 | pr_err("Key '%s' is in ima_blacklist_keyring\n", name); |
45 | return ERR_PTR(-EKEYREJECTED); | 45 | return ERR_PTR(-EKEYREJECTED); |
@@ -51,7 +51,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
51 | key_ref_t kref; | 51 | key_ref_t kref; |
52 | 52 | ||
53 | kref = keyring_search(make_key_ref(keyring, 1), | 53 | kref = keyring_search(make_key_ref(keyring, 1), |
54 | &key_type_asymmetric, name); | 54 | &key_type_asymmetric, name, true); |
55 | if (IS_ERR(kref)) | 55 | if (IS_ERR(kref)) |
56 | key = ERR_CAST(kref); | 56 | key = ERR_CAST(kref); |
57 | else | 57 | else |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 4305414795ae..aa361299a3ec 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -127,6 +127,7 @@ struct keyring_search_context { | |||
127 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ | 127 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ |
128 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ | 128 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ |
129 | #define KEYRING_SEARCH_SKIP_EXPIRED 0x0020 /* Ignore expired keys (intention to replace) */ | 129 | #define KEYRING_SEARCH_SKIP_EXPIRED 0x0020 /* Ignore expired keys (intention to replace) */ |
130 | #define KEYRING_SEARCH_RECURSE 0x0040 /* Search child keyrings also */ | ||
130 | 131 | ||
131 | int (*iterator)(const void *object, void *iterator_data); | 132 | int (*iterator)(const void *object, void *iterator_data); |
132 | 133 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 9f418e66f067..169409b611b0 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -762,7 +762,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
762 | } | 762 | } |
763 | 763 | ||
764 | /* do the search */ | 764 | /* do the search */ |
765 | key_ref = keyring_search(keyring_ref, ktype, description); | 765 | key_ref = keyring_search(keyring_ref, ktype, description, true); |
766 | if (IS_ERR(key_ref)) { | 766 | if (IS_ERR(key_ref)) { |
767 | ret = PTR_ERR(key_ref); | 767 | ret = PTR_ERR(key_ref); |
768 | 768 | ||
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index a5ee3b4d2eb8..20891cd198f0 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -685,6 +685,9 @@ descend_to_keyring: | |||
685 | * Non-keyrings avoid the leftmost branch of the root entirely (root | 685 | * Non-keyrings avoid the leftmost branch of the root entirely (root |
686 | * slots 1-15). | 686 | * slots 1-15). |
687 | */ | 687 | */ |
688 | if (!(ctx->flags & KEYRING_SEARCH_RECURSE)) | ||
689 | goto not_this_keyring; | ||
690 | |||
688 | ptr = READ_ONCE(keyring->keys.root); | 691 | ptr = READ_ONCE(keyring->keys.root); |
689 | if (!ptr) | 692 | if (!ptr) |
690 | goto not_this_keyring; | 693 | goto not_this_keyring; |
@@ -885,13 +888,15 @@ key_ref_t keyring_search_rcu(key_ref_t keyring_ref, | |||
885 | * @keyring: The root of the keyring tree to be searched. | 888 | * @keyring: The root of the keyring tree to be searched. |
886 | * @type: The type of keyring we want to find. | 889 | * @type: The type of keyring we want to find. |
887 | * @description: The name of the keyring we want to find. | 890 | * @description: The name of the keyring we want to find. |
891 | * @recurse: True to search the children of @keyring also | ||
888 | * | 892 | * |
889 | * As keyring_search_rcu() above, but using the current task's credentials and | 893 | * As keyring_search_rcu() above, but using the current task's credentials and |
890 | * type's default matching function and preferred search method. | 894 | * type's default matching function and preferred search method. |
891 | */ | 895 | */ |
892 | key_ref_t keyring_search(key_ref_t keyring, | 896 | key_ref_t keyring_search(key_ref_t keyring, |
893 | struct key_type *type, | 897 | struct key_type *type, |
894 | const char *description) | 898 | const char *description, |
899 | bool recurse) | ||
895 | { | 900 | { |
896 | struct keyring_search_context ctx = { | 901 | struct keyring_search_context ctx = { |
897 | .index_key.type = type, | 902 | .index_key.type = type, |
@@ -906,6 +911,8 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
906 | key_ref_t key; | 911 | key_ref_t key; |
907 | int ret; | 912 | int ret; |
908 | 913 | ||
914 | if (recurse) | ||
915 | ctx.flags |= KEYRING_SEARCH_RECURSE; | ||
909 | if (type->match_preparse) { | 916 | if (type->match_preparse) { |
910 | ret = type->match_preparse(&ctx.match_data); | 917 | ret = type->match_preparse(&ctx.match_data); |
911 | if (ret < 0) | 918 | if (ret < 0) |
@@ -1176,7 +1183,8 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
1176 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 1183 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
1177 | KEYRING_SEARCH_NO_UPDATE_TIME | | 1184 | KEYRING_SEARCH_NO_UPDATE_TIME | |
1178 | KEYRING_SEARCH_NO_CHECK_PERM | | 1185 | KEYRING_SEARCH_NO_CHECK_PERM | |
1179 | KEYRING_SEARCH_DETECT_TOO_DEEP), | 1186 | KEYRING_SEARCH_DETECT_TOO_DEEP | |
1187 | KEYRING_SEARCH_RECURSE), | ||
1180 | }; | 1188 | }; |
1181 | 1189 | ||
1182 | rcu_read_lock(); | 1190 | rcu_read_lock(); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index f081dceae3b9..b4f5ba56b9cb 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -170,7 +170,8 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
170 | .match_data.cmp = lookup_user_key_possessed, | 170 | .match_data.cmp = lookup_user_key_possessed, |
171 | .match_data.raw_data = key, | 171 | .match_data.raw_data = key, |
172 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 172 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
173 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, | 173 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
174 | KEYRING_SEARCH_RECURSE), | ||
174 | }; | 175 | }; |
175 | 176 | ||
176 | key_ref = make_key_ref(key, 0); | 177 | key_ref = make_key_ref(key, 0); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index f8ffb06d0297..b07f768d23dc 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -531,7 +531,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | |||
531 | struct keyring_search_context ctx = { | 531 | struct keyring_search_context ctx = { |
532 | .match_data.cmp = lookup_user_key_possessed, | 532 | .match_data.cmp = lookup_user_key_possessed, |
533 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 533 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
534 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, | 534 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
535 | KEYRING_SEARCH_RECURSE), | ||
535 | }; | 536 | }; |
536 | struct request_key_auth *rka; | 537 | struct request_key_auth *rka; |
537 | struct key *key; | 538 | struct key *key; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 36c55ef47b9e..1ffd3803ce29 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -569,7 +569,8 @@ struct key *request_key_and_link(struct key_type *type, | |||
569 | .match_data.raw_data = description, | 569 | .match_data.raw_data = description, |
570 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 570 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
571 | .flags = (KEYRING_SEARCH_DO_STATE_CHECK | | 571 | .flags = (KEYRING_SEARCH_DO_STATE_CHECK | |
572 | KEYRING_SEARCH_SKIP_EXPIRED), | 572 | KEYRING_SEARCH_SKIP_EXPIRED | |
573 | KEYRING_SEARCH_RECURSE), | ||
573 | }; | 574 | }; |
574 | struct key *key; | 575 | struct key *key; |
575 | key_ref_t key_ref; | 576 | key_ref_t key_ref; |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 99ed7a8a273d..f613987e8a63 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -252,7 +252,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
252 | .match_data.cmp = key_default_cmp, | 252 | .match_data.cmp = key_default_cmp, |
253 | .match_data.raw_data = description, | 253 | .match_data.raw_data = description, |
254 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 254 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
255 | .flags = KEYRING_SEARCH_DO_STATE_CHECK, | 255 | .flags = (KEYRING_SEARCH_DO_STATE_CHECK | |
256 | KEYRING_SEARCH_RECURSE), | ||
256 | }; | 257 | }; |
257 | struct key *authkey; | 258 | struct key *authkey; |
258 | key_ref_t authkey_ref; | 259 | key_ref_t authkey_ref; |