diff options
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r-- | security/keys/request_key.c | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index c411f9bb156b..381411941cc1 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -345,33 +345,34 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) | |||
345 | * May return a key that's already under construction instead if there was a | 345 | * May return a key that's already under construction instead if there was a |
346 | * race between two thread calling request_key(). | 346 | * race between two thread calling request_key(). |
347 | */ | 347 | */ |
348 | static int construct_alloc_key(struct key_type *type, | 348 | static int construct_alloc_key(struct keyring_search_context *ctx, |
349 | const char *description, | ||
350 | struct key *dest_keyring, | 349 | struct key *dest_keyring, |
351 | unsigned long flags, | 350 | unsigned long flags, |
352 | struct key_user *user, | 351 | struct key_user *user, |
353 | struct key **_key) | 352 | struct key **_key) |
354 | { | 353 | { |
355 | const struct cred *cred = current_cred(); | 354 | struct assoc_array_edit *edit; |
356 | unsigned long prealloc; | ||
357 | struct key *key; | 355 | struct key *key; |
358 | key_perm_t perm; | 356 | key_perm_t perm; |
359 | key_ref_t key_ref; | 357 | key_ref_t key_ref; |
360 | int ret; | 358 | int ret; |
361 | 359 | ||
362 | kenter("%s,%s,,,", type->name, description); | 360 | kenter("%s,%s,,,", |
361 | ctx->index_key.type->name, ctx->index_key.description); | ||
363 | 362 | ||
364 | *_key = NULL; | 363 | *_key = NULL; |
365 | mutex_lock(&user->cons_lock); | 364 | mutex_lock(&user->cons_lock); |
366 | 365 | ||
367 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | 366 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
368 | perm |= KEY_USR_VIEW; | 367 | perm |= KEY_USR_VIEW; |
369 | if (type->read) | 368 | if (ctx->index_key.type->read) |
370 | perm |= KEY_POS_READ; | 369 | perm |= KEY_POS_READ; |
371 | if (type == &key_type_keyring || type->update) | 370 | if (ctx->index_key.type == &key_type_keyring || |
371 | ctx->index_key.type->update) | ||
372 | perm |= KEY_POS_WRITE; | 372 | perm |= KEY_POS_WRITE; |
373 | 373 | ||
374 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 374 | key = key_alloc(ctx->index_key.type, ctx->index_key.description, |
375 | ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred, | ||
375 | perm, flags); | 376 | perm, flags); |
376 | if (IS_ERR(key)) | 377 | if (IS_ERR(key)) |
377 | goto alloc_failed; | 378 | goto alloc_failed; |
@@ -379,8 +380,7 @@ static int construct_alloc_key(struct key_type *type, | |||
379 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 380 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
380 | 381 | ||
381 | if (dest_keyring) { | 382 | if (dest_keyring) { |
382 | ret = __key_link_begin(dest_keyring, type, description, | 383 | ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit); |
383 | &prealloc); | ||
384 | if (ret < 0) | 384 | if (ret < 0) |
385 | goto link_prealloc_failed; | 385 | goto link_prealloc_failed; |
386 | } | 386 | } |
@@ -390,16 +390,16 @@ static int construct_alloc_key(struct key_type *type, | |||
390 | * waited for locks */ | 390 | * waited for locks */ |
391 | mutex_lock(&key_construction_mutex); | 391 | mutex_lock(&key_construction_mutex); |
392 | 392 | ||
393 | key_ref = search_process_keyrings(type, description, type->match, cred); | 393 | key_ref = search_process_keyrings(ctx); |
394 | if (!IS_ERR(key_ref)) | 394 | if (!IS_ERR(key_ref)) |
395 | goto key_already_present; | 395 | goto key_already_present; |
396 | 396 | ||
397 | if (dest_keyring) | 397 | if (dest_keyring) |
398 | __key_link(dest_keyring, key, &prealloc); | 398 | __key_link(key, &edit); |
399 | 399 | ||
400 | mutex_unlock(&key_construction_mutex); | 400 | mutex_unlock(&key_construction_mutex); |
401 | if (dest_keyring) | 401 | if (dest_keyring) |
402 | __key_link_end(dest_keyring, type, prealloc); | 402 | __key_link_end(dest_keyring, &ctx->index_key, edit); |
403 | mutex_unlock(&user->cons_lock); | 403 | mutex_unlock(&user->cons_lock); |
404 | *_key = key; | 404 | *_key = key; |
405 | kleave(" = 0 [%d]", key_serial(key)); | 405 | kleave(" = 0 [%d]", key_serial(key)); |
@@ -414,8 +414,8 @@ key_already_present: | |||
414 | if (dest_keyring) { | 414 | if (dest_keyring) { |
415 | ret = __key_link_check_live_key(dest_keyring, key); | 415 | ret = __key_link_check_live_key(dest_keyring, key); |
416 | if (ret == 0) | 416 | if (ret == 0) |
417 | __key_link(dest_keyring, key, &prealloc); | 417 | __key_link(key, &edit); |
418 | __key_link_end(dest_keyring, type, prealloc); | 418 | __key_link_end(dest_keyring, &ctx->index_key, edit); |
419 | if (ret < 0) | 419 | if (ret < 0) |
420 | goto link_check_failed; | 420 | goto link_check_failed; |
421 | } | 421 | } |
@@ -444,8 +444,7 @@ alloc_failed: | |||
444 | /* | 444 | /* |
445 | * Commence key construction. | 445 | * Commence key construction. |
446 | */ | 446 | */ |
447 | static struct key *construct_key_and_link(struct key_type *type, | 447 | static struct key *construct_key_and_link(struct keyring_search_context *ctx, |
448 | const char *description, | ||
449 | const char *callout_info, | 448 | const char *callout_info, |
450 | size_t callout_len, | 449 | size_t callout_len, |
451 | void *aux, | 450 | void *aux, |
@@ -464,8 +463,7 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
464 | 463 | ||
465 | construct_get_dest_keyring(&dest_keyring); | 464 | construct_get_dest_keyring(&dest_keyring); |
466 | 465 | ||
467 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, | 466 | ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); |
468 | &key); | ||
469 | key_user_put(user); | 467 | key_user_put(user); |
470 | 468 | ||
471 | if (ret == 0) { | 469 | if (ret == 0) { |
@@ -529,17 +527,24 @@ struct key *request_key_and_link(struct key_type *type, | |||
529 | struct key *dest_keyring, | 527 | struct key *dest_keyring, |
530 | unsigned long flags) | 528 | unsigned long flags) |
531 | { | 529 | { |
532 | const struct cred *cred = current_cred(); | 530 | struct keyring_search_context ctx = { |
531 | .index_key.type = type, | ||
532 | .index_key.description = description, | ||
533 | .cred = current_cred(), | ||
534 | .match = type->match, | ||
535 | .match_data = description, | ||
536 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
537 | }; | ||
533 | struct key *key; | 538 | struct key *key; |
534 | key_ref_t key_ref; | 539 | key_ref_t key_ref; |
535 | int ret; | 540 | int ret; |
536 | 541 | ||
537 | kenter("%s,%s,%p,%zu,%p,%p,%lx", | 542 | kenter("%s,%s,%p,%zu,%p,%p,%lx", |
538 | type->name, description, callout_info, callout_len, aux, | 543 | ctx.index_key.type->name, ctx.index_key.description, |
539 | dest_keyring, flags); | 544 | callout_info, callout_len, aux, dest_keyring, flags); |
540 | 545 | ||
541 | /* search all the process keyrings for a key */ | 546 | /* search all the process keyrings for a key */ |
542 | key_ref = search_process_keyrings(type, description, type->match, cred); | 547 | key_ref = search_process_keyrings(&ctx); |
543 | 548 | ||
544 | if (!IS_ERR(key_ref)) { | 549 | if (!IS_ERR(key_ref)) { |
545 | key = key_ref_to_ptr(key_ref); | 550 | key = key_ref_to_ptr(key_ref); |
@@ -562,9 +567,8 @@ struct key *request_key_and_link(struct key_type *type, | |||
562 | if (!callout_info) | 567 | if (!callout_info) |
563 | goto error; | 568 | goto error; |
564 | 569 | ||
565 | key = construct_key_and_link(type, description, callout_info, | 570 | key = construct_key_and_link(&ctx, callout_info, callout_len, |
566 | callout_len, aux, dest_keyring, | 571 | aux, dest_keyring, flags); |
567 | flags); | ||
568 | } | 572 | } |
569 | 573 | ||
570 | error: | 574 | error: |
@@ -592,8 +596,10 @@ int wait_for_key_construction(struct key *key, bool intr) | |||
592 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | 596 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); |
593 | if (ret < 0) | 597 | if (ret < 0) |
594 | return ret; | 598 | return ret; |
595 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | 599 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { |
600 | smp_rmb(); | ||
596 | return key->type_data.reject_error; | 601 | return key->type_data.reject_error; |
602 | } | ||
597 | return key_validate(key); | 603 | return key_validate(key); |
598 | } | 604 | } |
599 | EXPORT_SYMBOL(wait_for_key_construction); | 605 | EXPORT_SYMBOL(wait_for_key_construction); |