diff options
author | David Howells <dhowells@redhat.com> | 2013-09-24 05:35:15 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2013-09-24 05:35:15 -0400 |
commit | 4bdf0bc300314141e5475e145acb8b5ad846f00d (patch) | |
tree | ecf5a1d74d507410a9defa32edb4ea73edb9d205 /security/keys/keyring.c | |
parent | 16feef4340172b7dbb9cba60850e78fa6388adf1 (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.c | 70 |
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 | */ |
316 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 312 | key_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 */ |
490 | found: | 481 | found: |
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); |
498 | error_2: | 489 | error_2: |
499 | rcu_read_unlock(); | 490 | rcu_read_unlock(); |
500 | error: | 491 | error: |
@@ -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 | } |
523 | EXPORT_SYMBOL(keyring_search); | 523 | EXPORT_SYMBOL(keyring_search); |
524 | 524 | ||