diff options
Diffstat (limited to 'security/keys/keyring.c')
| -rw-r--r-- | security/keys/keyring.c | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 9c208c756df8..0639396dd441 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
| @@ -309,7 +309,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
| 309 | int ret; | 309 | int ret; |
| 310 | 310 | ||
| 311 | keyring = key_alloc(&key_type_keyring, description, | 311 | keyring = key_alloc(&key_type_keyring, description, |
| 312 | uid, gid, KEY_USR_ALL, not_in_quota); | 312 | uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota); |
| 313 | 313 | ||
| 314 | if (!IS_ERR(keyring)) { | 314 | if (!IS_ERR(keyring)) { |
| 315 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 315 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
| @@ -333,12 +333,13 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
| 333 | * - we rely on RCU to prevent the keyring lists from disappearing on us | 333 | * - we rely on RCU to prevent the keyring lists from disappearing on us |
| 334 | * - we return -EAGAIN if we didn't find any matching key | 334 | * - we return -EAGAIN if we didn't find any matching key |
| 335 | * - we return -ENOKEY if we only found negative matching keys | 335 | * - we return -ENOKEY if we only found negative matching keys |
| 336 | * - we propagate the possession attribute from the keyring ref to the key ref | ||
| 336 | */ | 337 | */ |
| 337 | struct key *keyring_search_aux(struct key *keyring, | 338 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
| 338 | struct task_struct *context, | 339 | struct task_struct *context, |
| 339 | struct key_type *type, | 340 | struct key_type *type, |
| 340 | const void *description, | 341 | const void *description, |
| 341 | key_match_func_t match) | 342 | key_match_func_t match) |
| 342 | { | 343 | { |
| 343 | struct { | 344 | struct { |
| 344 | struct keyring_list *keylist; | 345 | struct keyring_list *keylist; |
| @@ -347,29 +348,33 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 347 | 348 | ||
| 348 | struct keyring_list *keylist; | 349 | struct keyring_list *keylist; |
| 349 | struct timespec now; | 350 | struct timespec now; |
| 350 | struct key *key; | 351 | unsigned long possessed; |
| 352 | struct key *keyring, *key; | ||
| 353 | key_ref_t key_ref; | ||
| 351 | long err; | 354 | long err; |
| 352 | int sp, kix; | 355 | int sp, kix; |
| 353 | 356 | ||
| 357 | keyring = key_ref_to_ptr(keyring_ref); | ||
| 358 | possessed = is_key_possessed(keyring_ref); | ||
| 354 | key_check(keyring); | 359 | key_check(keyring); |
| 355 | 360 | ||
| 356 | rcu_read_lock(); | ||
| 357 | |||
| 358 | /* top keyring must have search permission to begin the search */ | 361 | /* top keyring must have search permission to begin the search */ |
| 359 | key = ERR_PTR(-EACCES); | 362 | key_ref = ERR_PTR(-EACCES); |
| 360 | if (!key_task_permission(keyring, context, KEY_SEARCH)) | 363 | if (!key_task_permission(keyring_ref, context, KEY_SEARCH)) |
| 361 | goto error; | 364 | goto error; |
| 362 | 365 | ||
| 363 | key = ERR_PTR(-ENOTDIR); | 366 | key_ref = ERR_PTR(-ENOTDIR); |
| 364 | if (keyring->type != &key_type_keyring) | 367 | if (keyring->type != &key_type_keyring) |
| 365 | goto error; | 368 | goto error; |
| 366 | 369 | ||
| 370 | rcu_read_lock(); | ||
| 371 | |||
| 367 | now = current_kernel_time(); | 372 | now = current_kernel_time(); |
| 368 | err = -EAGAIN; | 373 | err = -EAGAIN; |
| 369 | sp = 0; | 374 | sp = 0; |
| 370 | 375 | ||
| 371 | /* start processing a new keyring */ | 376 | /* start processing a new keyring */ |
| 372 | descend: | 377 | descend: |
| 373 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) | 378 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
| 374 | goto not_this_keyring; | 379 | goto not_this_keyring; |
| 375 | 380 | ||
| @@ -397,7 +402,8 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 397 | continue; | 402 | continue; |
| 398 | 403 | ||
| 399 | /* key must have search permissions */ | 404 | /* key must have search permissions */ |
| 400 | if (!key_task_permission(key, context, KEY_SEARCH)) | 405 | if (!key_task_permission(make_key_ref(key, possessed), |
| 406 | context, KEY_SEARCH)) | ||
| 401 | continue; | 407 | continue; |
| 402 | 408 | ||
| 403 | /* we set a different error code if we find a negative key */ | 409 | /* we set a different error code if we find a negative key */ |
| @@ -411,7 +417,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 411 | 417 | ||
| 412 | /* search through the keyrings nested in this one */ | 418 | /* search through the keyrings nested in this one */ |
| 413 | kix = 0; | 419 | kix = 0; |
| 414 | ascend: | 420 | ascend: |
| 415 | for (; kix < keylist->nkeys; kix++) { | 421 | for (; kix < keylist->nkeys; kix++) { |
| 416 | key = keylist->keys[kix]; | 422 | key = keylist->keys[kix]; |
| 417 | if (key->type != &key_type_keyring) | 423 | if (key->type != &key_type_keyring) |
| @@ -423,7 +429,8 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 423 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 429 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) |
| 424 | continue; | 430 | continue; |
| 425 | 431 | ||
| 426 | if (!key_task_permission(key, context, KEY_SEARCH)) | 432 | if (!key_task_permission(make_key_ref(key, possessed), |
| 433 | context, KEY_SEARCH)) | ||
| 427 | continue; | 434 | continue; |
| 428 | 435 | ||
| 429 | /* stack the current position */ | 436 | /* stack the current position */ |
| @@ -438,7 +445,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 438 | 445 | ||
| 439 | /* the keyring we're looking at was disqualified or didn't contain a | 446 | /* the keyring we're looking at was disqualified or didn't contain a |
| 440 | * matching key */ | 447 | * matching key */ |
| 441 | not_this_keyring: | 448 | not_this_keyring: |
| 442 | if (sp > 0) { | 449 | if (sp > 0) { |
| 443 | /* resume the processing of a keyring higher up in the tree */ | 450 | /* resume the processing of a keyring higher up in the tree */ |
| 444 | sp--; | 451 | sp--; |
| @@ -447,16 +454,18 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 447 | goto ascend; | 454 | goto ascend; |
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | key = ERR_PTR(err); | 457 | key_ref = ERR_PTR(err); |
| 451 | goto error; | 458 | goto error_2; |
| 452 | 459 | ||
| 453 | /* we found a viable match */ | 460 | /* we found a viable match */ |
| 454 | found: | 461 | found: |
| 455 | atomic_inc(&key->usage); | 462 | atomic_inc(&key->usage); |
| 456 | key_check(key); | 463 | key_check(key); |
| 457 | error: | 464 | key_ref = make_key_ref(key, possessed); |
| 465 | error_2: | ||
| 458 | rcu_read_unlock(); | 466 | rcu_read_unlock(); |
| 459 | return key; | 467 | error: |
| 468 | return key_ref; | ||
| 460 | 469 | ||
| 461 | } /* end keyring_search_aux() */ | 470 | } /* end keyring_search_aux() */ |
| 462 | 471 | ||
| @@ -469,9 +478,9 @@ struct key *keyring_search_aux(struct key *keyring, | |||
| 469 | * - we return -EAGAIN if we didn't find any matching key | 478 | * - we return -EAGAIN if we didn't find any matching key |
| 470 | * - we return -ENOKEY if we only found negative matching keys | 479 | * - we return -ENOKEY if we only found negative matching keys |
| 471 | */ | 480 | */ |
| 472 | struct key *keyring_search(struct key *keyring, | 481 | key_ref_t keyring_search(key_ref_t keyring, |
| 473 | struct key_type *type, | 482 | struct key_type *type, |
| 474 | const char *description) | 483 | const char *description) |
| 475 | { | 484 | { |
| 476 | if (!type->match) | 485 | if (!type->match) |
| 477 | return ERR_PTR(-ENOKEY); | 486 | return ERR_PTR(-ENOKEY); |
| @@ -488,15 +497,19 @@ EXPORT_SYMBOL(keyring_search); | |||
| 488 | * search the given keyring only (no recursion) | 497 | * search the given keyring only (no recursion) |
| 489 | * - keyring must be locked by caller | 498 | * - keyring must be locked by caller |
| 490 | */ | 499 | */ |
| 491 | struct key *__keyring_search_one(struct key *keyring, | 500 | key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
| 492 | const struct key_type *ktype, | 501 | const struct key_type *ktype, |
| 493 | const char *description, | 502 | const char *description, |
| 494 | key_perm_t perm) | 503 | key_perm_t perm) |
| 495 | { | 504 | { |
| 496 | struct keyring_list *klist; | 505 | struct keyring_list *klist; |
| 497 | struct key *key; | 506 | unsigned long possessed; |
| 507 | struct key *keyring, *key; | ||
| 498 | int loop; | 508 | int loop; |
| 499 | 509 | ||
| 510 | keyring = key_ref_to_ptr(keyring_ref); | ||
| 511 | possessed = is_key_possessed(keyring_ref); | ||
| 512 | |||
| 500 | rcu_read_lock(); | 513 | rcu_read_lock(); |
| 501 | 514 | ||
| 502 | klist = rcu_dereference(keyring->payload.subscriptions); | 515 | klist = rcu_dereference(keyring->payload.subscriptions); |
| @@ -507,21 +520,21 @@ struct key *__keyring_search_one(struct key *keyring, | |||
| 507 | if (key->type == ktype && | 520 | if (key->type == ktype && |
| 508 | (!key->type->match || | 521 | (!key->type->match || |
| 509 | key->type->match(key, description)) && | 522 | key->type->match(key, description)) && |
| 510 | key_permission(key, perm) && | 523 | key_permission(make_key_ref(key, possessed), |
| 524 | perm) && | ||
| 511 | !test_bit(KEY_FLAG_REVOKED, &key->flags) | 525 | !test_bit(KEY_FLAG_REVOKED, &key->flags) |
| 512 | ) | 526 | ) |
| 513 | goto found; | 527 | goto found; |
| 514 | } | 528 | } |
| 515 | } | 529 | } |
| 516 | 530 | ||
| 517 | key = ERR_PTR(-ENOKEY); | 531 | rcu_read_unlock(); |
| 518 | goto error; | 532 | return ERR_PTR(-ENOKEY); |
| 519 | 533 | ||
| 520 | found: | 534 | found: |
| 521 | atomic_inc(&key->usage); | 535 | atomic_inc(&key->usage); |
| 522 | error: | ||
| 523 | rcu_read_unlock(); | 536 | rcu_read_unlock(); |
| 524 | return key; | 537 | return make_key_ref(key, possessed); |
| 525 | 538 | ||
| 526 | } /* end __keyring_search_one() */ | 539 | } /* end __keyring_search_one() */ |
| 527 | 540 | ||
| @@ -603,7 +616,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
| 603 | if (strcmp(keyring->description, name) != 0) | 616 | if (strcmp(keyring->description, name) != 0) |
| 604 | continue; | 617 | continue; |
| 605 | 618 | ||
| 606 | if (!key_permission(keyring, KEY_SEARCH)) | 619 | if (!key_permission(make_key_ref(keyring, 0), |
| 620 | KEY_SEARCH)) | ||
| 607 | continue; | 621 | continue; |
| 608 | 622 | ||
| 609 | /* found a potential candidate, but we still need to | 623 | /* found a potential candidate, but we still need to |
