summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-06-26 16:02:32 -0400
committerDavid Howells <dhowells@redhat.com>2019-06-26 16:02:32 -0400
commitdcf49dbc8077e278ddd1bc7298abc781496e8a08 (patch)
treee187765e6336fefc35d83f5b75b7cbe1d4ec194a
parent355ef8e15885020da88f5ba2d85ce42b1d01f537 (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.rst10
-rw-r--r--certs/blacklist.c2
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c2
-rw-r--r--include/linux/key.h3
-rw-r--r--lib/digsig.c2
-rw-r--r--net/rxrpc/security.c2
-rw-r--r--security/integrity/digsig_asymmetric.c4
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/keys/keyring.c12
-rw-r--r--security/keys/proc.c3
-rw-r--r--security/keys/process_keys.c3
-rw-r--r--security/keys/request_key.c3
-rw-r--r--security/keys/request_key_auth.c3
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
342extern key_ref_t keyring_search(key_ref_t keyring, 342extern 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
346extern int keyring_add_key(struct key *keyring, 347extern 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 */
892key_ref_t keyring_search(key_ref_t keyring, 896key_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;