aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/key.h13
-rw-r--r--net/dns_resolver/dns_key.c10
-rw-r--r--security/keys/internal.h4
-rw-r--r--security/keys/keyring.c37
-rw-r--r--security/keys/proc.c2
-rw-r--r--security/keys/process_keys.c12
-rw-r--r--security/keys/request_key.c3
-rw-r--r--security/keys/request_key_auth.c3
-rw-r--r--security/keys/user_defined.c4
9 files changed, 59 insertions, 29 deletions
diff --git a/include/linux/key.h b/include/linux/key.h
index b2bb01719561..ef19b99aff98 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key)
276 return key ? key->serial : 0; 276 return key ? key->serial : 0;
277} 277}
278 278
279/**
280 * key_is_instantiated - Determine if a key has been positively instantiated
281 * @key: The key to check.
282 *
283 * Return true if the specified key has been positively instantiated, false
284 * otherwise.
285 */
286static inline bool key_is_instantiated(const struct key *key)
287{
288 return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
289 !test_bit(KEY_FLAG_NEGATIVE, &key->flags);
290}
291
279#define rcu_dereference_key(KEY) \ 292#define rcu_dereference_key(KEY) \
280 (rcu_dereference_protected((KEY)->payload.rcudata, \ 293 (rcu_dereference_protected((KEY)->payload.rcudata, \
281 rwsem_is_locked(&((struct key *)(KEY))->sem))) 294 rwsem_is_locked(&((struct key *)(KEY))->sem)))
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index cfa7a5e1c5c9..fa000d26dc60 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m)
212 int err = key->type_data.x[0]; 212 int err = key->type_data.x[0];
213 213
214 seq_puts(m, key->description); 214 seq_puts(m, key->description);
215 if (err) 215 if (key_is_instantiated(key)) {
216 seq_printf(m, ": %d", err); 216 if (err)
217 else 217 seq_printf(m, ": %d", err);
218 seq_printf(m, ": %u", key->datalen); 218 else
219 seq_printf(m, ": %u", key->datalen);
220 }
219} 221}
220 222
221/* 223/*
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 07a025f81902..f375152a2500 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
109 const struct cred *cred, 109 const struct cred *cred,
110 struct key_type *type, 110 struct key_type *type,
111 const void *description, 111 const void *description,
112 key_match_func_t match); 112 key_match_func_t match,
113 bool no_state_check);
113 114
114extern key_ref_t search_my_process_keyrings(struct key_type *type, 115extern key_ref_t search_my_process_keyrings(struct key_type *type,
115 const void *description, 116 const void *description,
116 key_match_func_t match, 117 key_match_func_t match,
118 bool no_state_check,
117 const struct cred *cred); 119 const struct cred *cred);
118extern key_ref_t search_process_keyrings(struct key_type *type, 120extern key_ref_t search_process_keyrings(struct key_type *type,
119 const void *description, 121 const void *description,
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index cdd2f3f88c88..a06ffab38568 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
176 else 176 else
177 seq_puts(m, "[anon]"); 177 seq_puts(m, "[anon]");
178 178
179 rcu_read_lock(); 179 if (key_is_instantiated(keyring)) {
180 klist = rcu_dereference(keyring->payload.subscriptions); 180 rcu_read_lock();
181 if (klist) 181 klist = rcu_dereference(keyring->payload.subscriptions);
182 seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); 182 if (klist)
183 else 183 seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
184 seq_puts(m, ": empty"); 184 else
185 rcu_read_unlock(); 185 seq_puts(m, ": empty");
186 rcu_read_unlock();
187 }
186} 188}
187 189
188/* 190/*
@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
271 * @type: The type of key to search for. 273 * @type: The type of key to search for.
272 * @description: Parameter for @match. 274 * @description: Parameter for @match.
273 * @match: Function to rule on whether or not a key is the one required. 275 * @match: Function to rule on whether or not a key is the one required.
276 * @no_state_check: Don't check if a matching key is bad
274 * 277 *
275 * Search the supplied keyring tree for a key that matches the criteria given. 278 * Search the supplied keyring tree for a key that matches the criteria given.
276 * The root keyring and any linked keyrings must grant Search permission to the 279 * The root keyring and any linked keyrings must grant Search permission to the
@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
303 const struct cred *cred, 306 const struct cred *cred,
304 struct key_type *type, 307 struct key_type *type,
305 const void *description, 308 const void *description,
306 key_match_func_t match) 309 key_match_func_t match,
310 bool no_state_check)
307{ 311{
308 struct { 312 struct {
309 struct keyring_list *keylist; 313 struct keyring_list *keylist;
@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
345 kflags = keyring->flags; 349 kflags = keyring->flags;
346 if (keyring->type == type && match(keyring, description)) { 350 if (keyring->type == type && match(keyring, description)) {
347 key = keyring; 351 key = keyring;
352 if (no_state_check)
353 goto found;
348 354
349 /* check it isn't negative and hasn't expired or been 355 /* check it isn't negative and hasn't expired or been
350 * revoked */ 356 * revoked */
@@ -384,11 +390,13 @@ descend:
384 continue; 390 continue;
385 391
386 /* skip revoked keys and expired keys */ 392 /* skip revoked keys and expired keys */
387 if (kflags & (1 << KEY_FLAG_REVOKED)) 393 if (!no_state_check) {
388 continue; 394 if (kflags & (1 << KEY_FLAG_REVOKED))
395 continue;
389 396
390 if (key->expiry && now.tv_sec >= key->expiry) 397 if (key->expiry && now.tv_sec >= key->expiry)
391 continue; 398 continue;
399 }
392 400
393 /* keys that don't match */ 401 /* keys that don't match */
394 if (!match(key, description)) 402 if (!match(key, description))
@@ -399,6 +407,9 @@ descend:
399 cred, KEY_SEARCH) < 0) 407 cred, KEY_SEARCH) < 0)
400 continue; 408 continue;
401 409
410 if (no_state_check)
411 goto found;
412
402 /* we set a different error code if we pass a negative key */ 413 /* we set a different error code if we pass a negative key */
403 if (kflags & (1 << KEY_FLAG_NEGATIVE)) { 414 if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
404 err = key->type_data.reject_error; 415 err = key->type_data.reject_error;
@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring,
478 return ERR_PTR(-ENOKEY); 489 return ERR_PTR(-ENOKEY);
479 490
480 return keyring_search_aux(keyring, current->cred, 491 return keyring_search_aux(keyring, current->cred,
481 type, description, type->match); 492 type, description, type->match, false);
482} 493}
483EXPORT_SYMBOL(keyring_search); 494EXPORT_SYMBOL(keyring_search);
484 495
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 525cf8a29cdd..49bbc97943ad 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
199 if (key->perm & KEY_POS_VIEW) { 199 if (key->perm & KEY_POS_VIEW) {
200 skey_ref = search_my_process_keyrings(key->type, key, 200 skey_ref = search_my_process_keyrings(key->type, key,
201 lookup_user_key_possessed, 201 lookup_user_key_possessed,
202 cred); 202 true, cred);
203 if (!IS_ERR(skey_ref)) { 203 if (!IS_ERR(skey_ref)) {
204 key_ref_put(skey_ref); 204 key_ref_put(skey_ref);
205 key_ref = make_key_ref(key, 1); 205 key_ref = make_key_ref(key, 1);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 930634e45149..6c0480db8885 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk)
331key_ref_t search_my_process_keyrings(struct key_type *type, 331key_ref_t search_my_process_keyrings(struct key_type *type,
332 const void *description, 332 const void *description,
333 key_match_func_t match, 333 key_match_func_t match,
334 bool no_state_check,
334 const struct cred *cred) 335 const struct cred *cred)
335{ 336{
336 key_ref_t key_ref, ret, err; 337 key_ref_t key_ref, ret, err;
@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
350 if (cred->thread_keyring) { 351 if (cred->thread_keyring) {
351 key_ref = keyring_search_aux( 352 key_ref = keyring_search_aux(
352 make_key_ref(cred->thread_keyring, 1), 353 make_key_ref(cred->thread_keyring, 1),
353 cred, type, description, match); 354 cred, type, description, match, no_state_check);
354 if (!IS_ERR(key_ref)) 355 if (!IS_ERR(key_ref))
355 goto found; 356 goto found;
356 357
@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
371 if (cred->tgcred->process_keyring) { 372 if (cred->tgcred->process_keyring) {
372 key_ref = keyring_search_aux( 373 key_ref = keyring_search_aux(
373 make_key_ref(cred->tgcred->process_keyring, 1), 374 make_key_ref(cred->tgcred->process_keyring, 1),
374 cred, type, description, match); 375 cred, type, description, match, no_state_check);
375 if (!IS_ERR(key_ref)) 376 if (!IS_ERR(key_ref))
376 goto found; 377 goto found;
377 378
@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
395 make_key_ref(rcu_dereference( 396 make_key_ref(rcu_dereference(
396 cred->tgcred->session_keyring), 397 cred->tgcred->session_keyring),
397 1), 398 1),
398 cred, type, description, match); 399 cred, type, description, match, no_state_check);
399 rcu_read_unlock(); 400 rcu_read_unlock();
400 401
401 if (!IS_ERR(key_ref)) 402 if (!IS_ERR(key_ref))
@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
417 else if (cred->user->session_keyring) { 418 else if (cred->user->session_keyring) {
418 key_ref = keyring_search_aux( 419 key_ref = keyring_search_aux(
419 make_key_ref(cred->user->session_keyring, 1), 420 make_key_ref(cred->user->session_keyring, 1),
420 cred, type, description, match); 421 cred, type, description, match, no_state_check);
421 if (!IS_ERR(key_ref)) 422 if (!IS_ERR(key_ref))
422 goto found; 423 goto found;
423 424
@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
459 460
460 might_sleep(); 461 might_sleep();
461 462
462 key_ref = search_my_process_keyrings(type, description, match, cred); 463 key_ref = search_my_process_keyrings(type, description, match,
464 false, cred);
463 if (!IS_ERR(key_ref)) 465 if (!IS_ERR(key_ref))
464 goto found; 466 goto found;
465 err = key_ref; 467 err = key_ref;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index df3c0417ee40..b18a71745901 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type,
530 dest_keyring, flags); 530 dest_keyring, flags);
531 531
532 /* search all the process keyrings for a key */ 532 /* search all the process keyrings for a key */
533 key_ref = search_process_keyrings(type, description, type->match, 533 key_ref = search_process_keyrings(type, description, type->match, cred);
534 cred);
535 534
536 if (!IS_ERR(key_ref)) { 535 if (!IS_ERR(key_ref)) {
537 key = key_ref_to_ptr(key_ref); 536 key = key_ref_to_ptr(key_ref);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 68164031a74e..f6337c9082eb 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key,
59 59
60 seq_puts(m, "key:"); 60 seq_puts(m, "key:");
61 seq_puts(m, key->description); 61 seq_puts(m, key->description);
62 seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); 62 if (key_is_instantiated(key))
63 seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
63} 64}
64 65
65/* 66/*
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index c6ca8662a468..63bb1aaffc0a 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -169,8 +169,8 @@ EXPORT_SYMBOL_GPL(user_destroy);
169void user_describe(const struct key *key, struct seq_file *m) 169void user_describe(const struct key *key, struct seq_file *m)
170{ 170{
171 seq_puts(m, key->description); 171 seq_puts(m, key->description);
172 172 if (key_is_instantiated(key))
173 seq_printf(m, ": %u", key->datalen); 173 seq_printf(m, ": %u", key->datalen);
174} 174}
175 175
176EXPORT_SYMBOL_GPL(user_describe); 176EXPORT_SYMBOL_GPL(user_describe);