aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-09-24 05:35:15 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-24 05:35:15 -0400
commit4bdf0bc300314141e5475e145acb8b5ad846f00d (patch)
treeecf5a1d74d507410a9defa32edb4ea73edb9d205 /security/keys/keyring.c
parent16feef4340172b7dbb9cba60850e78fa6388adf1 (diff)
KEYS: Introduce a search context structure
Search functions pass around a bunch of arguments, each of which gets copied with each call. Introduce a search context structure to hold these. Whilst we're at it, create a search flag that indicates whether the search should be directly to the description or whether it should iterate through all keys looking for a non-description match. This will be useful when keyrings use a generic data struct with generic routines to manage their content as the search terms can just be passed through to the iterator callback function. Also, for future use, the data to be supplied to the match function is separated from the description pointer in the search context. This makes it clear which is being supplied. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c70
1 files changed, 35 insertions, 35 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index c7f59f9dd7b6..b42f2d4f7f83 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -280,11 +280,7 @@ EXPORT_SYMBOL(keyring_alloc);
280/** 280/**
281 * keyring_search_aux - Search a keyring tree for a key matching some criteria 281 * keyring_search_aux - Search a keyring tree for a key matching some criteria
282 * @keyring_ref: A pointer to the keyring with possession indicator. 282 * @keyring_ref: A pointer to the keyring with possession indicator.
283 * @cred: The credentials to use for permissions checks. 283 * @ctx: The keyring search context.
284 * @type: The type of key to search for.
285 * @description: Parameter for @match.
286 * @match: Function to rule on whether or not a key is the one required.
287 * @no_state_check: Don't check if a matching key is bad
288 * 284 *
289 * Search the supplied keyring tree for a key that matches the criteria given. 285 * Search the supplied keyring tree for a key that matches the criteria given.
290 * The root keyring and any linked keyrings must grant Search permission to the 286 * The root keyring and any linked keyrings must grant Search permission to the
@@ -314,11 +310,7 @@ EXPORT_SYMBOL(keyring_alloc);
314 * @keyring_ref is propagated to the returned key reference. 310 * @keyring_ref is propagated to the returned key reference.
315 */ 311 */
316key_ref_t keyring_search_aux(key_ref_t keyring_ref, 312key_ref_t keyring_search_aux(key_ref_t keyring_ref,
317 const struct cred *cred, 313 struct keyring_search_context *ctx)
318 struct key_type *type,
319 const void *description,
320 key_match_func_t match,
321 bool no_state_check)
322{ 314{
323 struct { 315 struct {
324 /* Need a separate keylist pointer for RCU purposes */ 316 /* Need a separate keylist pointer for RCU purposes */
@@ -328,20 +320,18 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
328 } stack[KEYRING_SEARCH_MAX_DEPTH]; 320 } stack[KEYRING_SEARCH_MAX_DEPTH];
329 321
330 struct keyring_list *keylist; 322 struct keyring_list *keylist;
331 struct timespec now;
332 unsigned long kflags; 323 unsigned long kflags;
333 struct key *keyring, *key; 324 struct key *keyring, *key;
334 key_ref_t key_ref; 325 key_ref_t key_ref;
335 bool possessed;
336 long err; 326 long err;
337 int sp, nkeys, kix; 327 int sp, nkeys, kix;
338 328
339 keyring = key_ref_to_ptr(keyring_ref); 329 keyring = key_ref_to_ptr(keyring_ref);
340 possessed = is_key_possessed(keyring_ref); 330 ctx->possessed = is_key_possessed(keyring_ref);
341 key_check(keyring); 331 key_check(keyring);
342 332
343 /* top keyring must have search permission to begin the search */ 333 /* top keyring must have search permission to begin the search */
344 err = key_task_permission(keyring_ref, cred, KEY_SEARCH); 334 err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
345 if (err < 0) { 335 if (err < 0) {
346 key_ref = ERR_PTR(err); 336 key_ref = ERR_PTR(err);
347 goto error; 337 goto error;
@@ -353,7 +343,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
353 343
354 rcu_read_lock(); 344 rcu_read_lock();
355 345
356 now = current_kernel_time(); 346 ctx->now = current_kernel_time();
357 err = -EAGAIN; 347 err = -EAGAIN;
358 sp = 0; 348 sp = 0;
359 349
@@ -361,16 +351,17 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
361 * are looking for */ 351 * are looking for */
362 key_ref = ERR_PTR(-EAGAIN); 352 key_ref = ERR_PTR(-EAGAIN);
363 kflags = keyring->flags; 353 kflags = keyring->flags;
364 if (keyring->type == type && match(keyring, description)) { 354 if (keyring->type == ctx->index_key.type &&
355 ctx->match(keyring, ctx->match_data)) {
365 key = keyring; 356 key = keyring;
366 if (no_state_check) 357 if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
367 goto found; 358 goto found;
368 359
369 /* check it isn't negative and hasn't expired or been 360 /* check it isn't negative and hasn't expired or been
370 * revoked */ 361 * revoked */
371 if (kflags & (1 << KEY_FLAG_REVOKED)) 362 if (kflags & (1 << KEY_FLAG_REVOKED))
372 goto error_2; 363 goto error_2;
373 if (key->expiry && now.tv_sec >= key->expiry) 364 if (key->expiry && ctx->now.tv_sec >= key->expiry)
374 goto error_2; 365 goto error_2;
375 key_ref = ERR_PTR(key->type_data.reject_error); 366 key_ref = ERR_PTR(key->type_data.reject_error);
376 if (kflags & (1 << KEY_FLAG_NEGATIVE)) 367 if (kflags & (1 << KEY_FLAG_NEGATIVE))
@@ -384,7 +375,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
384 if (kflags & ((1 << KEY_FLAG_INVALIDATED) | 375 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
385 (1 << KEY_FLAG_REVOKED) | 376 (1 << KEY_FLAG_REVOKED) |
386 (1 << KEY_FLAG_NEGATIVE)) || 377 (1 << KEY_FLAG_NEGATIVE)) ||
387 (keyring->expiry && now.tv_sec >= keyring->expiry)) 378 (keyring->expiry && ctx->now.tv_sec >= keyring->expiry))
388 goto error_2; 379 goto error_2;
389 380
390 /* start processing a new keyring */ 381 /* start processing a new keyring */
@@ -406,29 +397,29 @@ descend:
406 kflags = key->flags; 397 kflags = key->flags;
407 398
408 /* ignore keys not of this type */ 399 /* ignore keys not of this type */
409 if (key->type != type) 400 if (key->type != ctx->index_key.type)
410 continue; 401 continue;
411 402
412 /* skip invalidated, revoked and expired keys */ 403 /* skip invalidated, revoked and expired keys */
413 if (!no_state_check) { 404 if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) {
414 if (kflags & ((1 << KEY_FLAG_INVALIDATED) | 405 if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
415 (1 << KEY_FLAG_REVOKED))) 406 (1 << KEY_FLAG_REVOKED)))
416 continue; 407 continue;
417 408
418 if (key->expiry && now.tv_sec >= key->expiry) 409 if (key->expiry && ctx->now.tv_sec >= key->expiry)
419 continue; 410 continue;
420 } 411 }
421 412
422 /* keys that don't match */ 413 /* keys that don't match */
423 if (!match(key, description)) 414 if (!ctx->match(key, ctx->match_data))
424 continue; 415 continue;
425 416
426 /* key must have search permissions */ 417 /* key must have search permissions */
427 if (key_task_permission(make_key_ref(key, possessed), 418 if (key_task_permission(make_key_ref(key, ctx->possessed),
428 cred, KEY_SEARCH) < 0) 419 ctx->cred, KEY_SEARCH) < 0)
429 continue; 420 continue;
430 421
431 if (no_state_check) 422 if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
432 goto found; 423 goto found;
433 424
434 /* we set a different error code if we pass a negative key */ 425 /* we set a different error code if we pass a negative key */
@@ -456,8 +447,8 @@ ascend:
456 if (sp >= KEYRING_SEARCH_MAX_DEPTH) 447 if (sp >= KEYRING_SEARCH_MAX_DEPTH)
457 continue; 448 continue;
458 449
459 if (key_task_permission(make_key_ref(key, possessed), 450 if (key_task_permission(make_key_ref(key, ctx->possessed),
460 cred, KEY_SEARCH) < 0) 451 ctx->cred, KEY_SEARCH) < 0)
461 continue; 452 continue;
462 453
463 /* stack the current position */ 454 /* stack the current position */
@@ -489,12 +480,12 @@ not_this_keyring:
489 /* we found a viable match */ 480 /* we found a viable match */
490found: 481found:
491 atomic_inc(&key->usage); 482 atomic_inc(&key->usage);
492 key->last_used_at = now.tv_sec; 483 key->last_used_at = ctx->now.tv_sec;
493 keyring->last_used_at = now.tv_sec; 484 keyring->last_used_at = ctx->now.tv_sec;
494 while (sp > 0) 485 while (sp > 0)
495 stack[--sp].keyring->last_used_at = now.tv_sec; 486 stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
496 key_check(key); 487 key_check(key);
497 key_ref = make_key_ref(key, possessed); 488 key_ref = make_key_ref(key, ctx->possessed);
498error_2: 489error_2:
499 rcu_read_unlock(); 490 rcu_read_unlock();
500error: 491error:
@@ -514,11 +505,20 @@ key_ref_t keyring_search(key_ref_t keyring,
514 struct key_type *type, 505 struct key_type *type,
515 const char *description) 506 const char *description)
516{ 507{
517 if (!type->match) 508 struct keyring_search_context ctx = {
509 .index_key.type = type,
510 .index_key.description = description,
511 .cred = current_cred(),
512 .match = type->match,
513 .match_data = description,
514 .flags = (type->def_lookup_type |
515 KEYRING_SEARCH_DO_STATE_CHECK),
516 };
517
518 if (!ctx.match)
518 return ERR_PTR(-ENOKEY); 519 return ERR_PTR(-ENOKEY);
519 520
520 return keyring_search_aux(keyring, current->cred, 521 return keyring_search_aux(keyring, &ctx);
521 type, description, type->match, false);
522} 522}
523EXPORT_SYMBOL(keyring_search); 523EXPORT_SYMBOL(keyring_search);
524 524