diff options
| author | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-12-17 09:27:08 -0500 |
| commit | bb799d3b980eb803ca2da4a4eefbd9308f8d988a (patch) | |
| tree | 69fbe0cd6d47b23a50f5e1d87bf7489532fae149 /security/keys/request_key.c | |
| parent | 919fc6e34831d1c2b58bfb5ae261dc3facc9b269 (diff) | |
| parent | 319e2e3f63c348a9b66db4667efa73178e18b17d (diff) | |
Merge tag 'v3.13-rc4' into core/locking
Merge Linux 3.13-rc4, to refresh this rather old tree with the latest fixes.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
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); |
