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 |