diff options
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r-- | security/keys/process_keys.c | 179 |
1 files changed, 111 insertions, 68 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 972e30172687..34db087bbcc7 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -165,7 +165,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
165 | /* | 165 | /* |
166 | * make sure a process keyring is installed | 166 | * make sure a process keyring is installed |
167 | */ | 167 | */ |
168 | static int install_process_keyring(struct task_struct *tsk) | 168 | int install_process_keyring(struct task_struct *tsk) |
169 | { | 169 | { |
170 | unsigned long flags; | 170 | unsigned long flags; |
171 | struct key *keyring; | 171 | struct key *keyring; |
@@ -376,12 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
376 | * - we return -EAGAIN if we didn't find any matching key | 376 | * - we return -EAGAIN if we didn't find any matching key |
377 | * - we return -ENOKEY if we found only negative matching keys | 377 | * - we return -ENOKEY if we found only negative matching keys |
378 | */ | 378 | */ |
379 | struct key *search_process_keyrings_aux(struct key_type *type, | 379 | struct key *search_process_keyrings(struct key_type *type, |
380 | const void *description, | 380 | const void *description, |
381 | key_match_func_t match) | 381 | key_match_func_t match, |
382 | struct task_struct *context) | ||
382 | { | 383 | { |
383 | struct task_struct *tsk = current; | 384 | struct request_key_auth *rka; |
384 | struct key *key, *ret, *err; | 385 | struct key *key, *ret, *err, *instkey; |
385 | 386 | ||
386 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 387 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
387 | * searchable, but we failed to find a key or we found a negative key; | 388 | * searchable, but we failed to find a key or we found a negative key; |
@@ -395,9 +396,9 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
395 | err = ERR_PTR(-EAGAIN); | 396 | err = ERR_PTR(-EAGAIN); |
396 | 397 | ||
397 | /* search the thread keyring first */ | 398 | /* search the thread keyring first */ |
398 | if (tsk->thread_keyring) { | 399 | if (context->thread_keyring) { |
399 | key = keyring_search_aux(tsk->thread_keyring, type, | 400 | key = keyring_search_aux(context->thread_keyring, |
400 | description, match); | 401 | context, type, description, match); |
401 | if (!IS_ERR(key)) | 402 | if (!IS_ERR(key)) |
402 | goto found; | 403 | goto found; |
403 | 404 | ||
@@ -415,9 +416,9 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
415 | } | 416 | } |
416 | 417 | ||
417 | /* search the process keyring second */ | 418 | /* search the process keyring second */ |
418 | if (tsk->signal->process_keyring) { | 419 | if (context->signal->process_keyring) { |
419 | key = keyring_search_aux(tsk->signal->process_keyring, | 420 | key = keyring_search_aux(context->signal->process_keyring, |
420 | type, description, match); | 421 | context, type, description, match); |
421 | if (!IS_ERR(key)) | 422 | if (!IS_ERR(key)) |
422 | goto found; | 423 | goto found; |
423 | 424 | ||
@@ -434,53 +435,93 @@ struct key *search_process_keyrings_aux(struct key_type *type, | |||
434 | } | 435 | } |
435 | } | 436 | } |
436 | 437 | ||
437 | /* search the session keyring last */ | 438 | /* search the session keyring */ |
438 | if (tsk->signal->session_keyring) { | 439 | if (context->signal->session_keyring) { |
439 | rcu_read_lock(); | 440 | rcu_read_lock(); |
440 | key = keyring_search_aux( | 441 | key = keyring_search_aux( |
441 | rcu_dereference(tsk->signal->session_keyring), | 442 | rcu_dereference(context->signal->session_keyring), |
442 | type, description, match); | 443 | context, type, description, match); |
443 | rcu_read_unlock(); | 444 | rcu_read_unlock(); |
445 | |||
446 | if (!IS_ERR(key)) | ||
447 | goto found; | ||
448 | |||
449 | switch (PTR_ERR(key)) { | ||
450 | case -EAGAIN: /* no key */ | ||
451 | if (ret) | ||
452 | break; | ||
453 | case -ENOKEY: /* negative key */ | ||
454 | ret = key; | ||
455 | break; | ||
456 | default: | ||
457 | err = key; | ||
458 | break; | ||
459 | } | ||
460 | |||
461 | /* if this process has a session keyring and that has an | ||
462 | * instantiation authorisation key in the bottom level, then we | ||
463 | * also search the keyrings of the process mentioned there */ | ||
464 | if (context != current) | ||
465 | goto no_key; | ||
466 | |||
467 | rcu_read_lock(); | ||
468 | instkey = __keyring_search_one( | ||
469 | rcu_dereference(context->signal->session_keyring), | ||
470 | &key_type_request_key_auth, NULL, 0); | ||
471 | rcu_read_unlock(); | ||
472 | |||
473 | if (IS_ERR(instkey)) | ||
474 | goto no_key; | ||
475 | |||
476 | rka = instkey->payload.data; | ||
477 | |||
478 | key = search_process_keyrings(type, description, match, | ||
479 | rka->context); | ||
480 | key_put(instkey); | ||
481 | |||
482 | if (!IS_ERR(key)) | ||
483 | goto found; | ||
484 | |||
485 | switch (PTR_ERR(key)) { | ||
486 | case -EAGAIN: /* no key */ | ||
487 | if (ret) | ||
488 | break; | ||
489 | case -ENOKEY: /* negative key */ | ||
490 | ret = key; | ||
491 | break; | ||
492 | default: | ||
493 | err = key; | ||
494 | break; | ||
495 | } | ||
444 | } | 496 | } |
497 | /* or search the user-session keyring */ | ||
445 | else { | 498 | else { |
446 | key = keyring_search_aux(tsk->user->session_keyring, | 499 | key = keyring_search_aux(context->user->session_keyring, |
447 | type, description, match); | 500 | context, type, description, match); |
448 | } | 501 | if (!IS_ERR(key)) |
449 | 502 | goto found; | |
450 | if (!IS_ERR(key)) | ||
451 | goto found; | ||
452 | 503 | ||
453 | switch (PTR_ERR(key)) { | 504 | switch (PTR_ERR(key)) { |
454 | case -EAGAIN: /* no key */ | 505 | case -EAGAIN: /* no key */ |
455 | if (ret) | 506 | if (ret) |
507 | break; | ||
508 | case -ENOKEY: /* negative key */ | ||
509 | ret = key; | ||
456 | break; | 510 | break; |
457 | case -ENOKEY: /* negative key */ | 511 | default: |
458 | ret = key; | 512 | err = key; |
459 | break; | 513 | break; |
460 | default: | 514 | } |
461 | err = key; | ||
462 | break; | ||
463 | } | 515 | } |
464 | 516 | ||
517 | |||
518 | no_key: | ||
465 | /* no key - decide on the error we're going to go for */ | 519 | /* no key - decide on the error we're going to go for */ |
466 | key = ret ? ret : err; | 520 | key = ret ? ret : err; |
467 | 521 | ||
468 | found: | 522 | found: |
469 | return key; | 523 | return key; |
470 | 524 | ||
471 | } /* end search_process_keyrings_aux() */ | ||
472 | |||
473 | /*****************************************************************************/ | ||
474 | /* | ||
475 | * search the process keyrings for the first matching key | ||
476 | * - we return -EAGAIN if we didn't find any matching key | ||
477 | * - we return -ENOKEY if we found only negative matching keys | ||
478 | */ | ||
479 | struct key *search_process_keyrings(struct key_type *type, | ||
480 | const char *description) | ||
481 | { | ||
482 | return search_process_keyrings_aux(type, description, type->match); | ||
483 | |||
484 | } /* end search_process_keyrings() */ | 525 | } /* end search_process_keyrings() */ |
485 | 526 | ||
486 | /*****************************************************************************/ | 527 | /*****************************************************************************/ |
@@ -489,72 +530,73 @@ struct key *search_process_keyrings(struct key_type *type, | |||
489 | * - don't create special keyrings unless so requested | 530 | * - don't create special keyrings unless so requested |
490 | * - partially constructed keys aren't found unless requested | 531 | * - partially constructed keys aren't found unless requested |
491 | */ | 532 | */ |
492 | struct key *lookup_user_key(key_serial_t id, int create, int partial, | 533 | struct key *lookup_user_key(struct task_struct *context, key_serial_t id, |
493 | key_perm_t perm) | 534 | int create, int partial, key_perm_t perm) |
494 | { | 535 | { |
495 | struct task_struct *tsk = current; | ||
496 | unsigned long flags; | ||
497 | struct key *key; | 536 | struct key *key; |
498 | int ret; | 537 | int ret; |
499 | 538 | ||
539 | if (!context) | ||
540 | context = current; | ||
541 | |||
500 | key = ERR_PTR(-ENOKEY); | 542 | key = ERR_PTR(-ENOKEY); |
501 | 543 | ||
502 | switch (id) { | 544 | switch (id) { |
503 | case KEY_SPEC_THREAD_KEYRING: | 545 | case KEY_SPEC_THREAD_KEYRING: |
504 | if (!tsk->thread_keyring) { | 546 | if (!context->thread_keyring) { |
505 | if (!create) | 547 | if (!create) |
506 | goto error; | 548 | goto error; |
507 | 549 | ||
508 | ret = install_thread_keyring(tsk); | 550 | ret = install_thread_keyring(context); |
509 | if (ret < 0) { | 551 | if (ret < 0) { |
510 | key = ERR_PTR(ret); | 552 | key = ERR_PTR(ret); |
511 | goto error; | 553 | goto error; |
512 | } | 554 | } |
513 | } | 555 | } |
514 | 556 | ||
515 | key = tsk->thread_keyring; | 557 | key = context->thread_keyring; |
516 | atomic_inc(&key->usage); | 558 | atomic_inc(&key->usage); |
517 | break; | 559 | break; |
518 | 560 | ||
519 | case KEY_SPEC_PROCESS_KEYRING: | 561 | case KEY_SPEC_PROCESS_KEYRING: |
520 | if (!tsk->signal->process_keyring) { | 562 | if (!context->signal->process_keyring) { |
521 | if (!create) | 563 | if (!create) |
522 | goto error; | 564 | goto error; |
523 | 565 | ||
524 | ret = install_process_keyring(tsk); | 566 | ret = install_process_keyring(context); |
525 | if (ret < 0) { | 567 | if (ret < 0) { |
526 | key = ERR_PTR(ret); | 568 | key = ERR_PTR(ret); |
527 | goto error; | 569 | goto error; |
528 | } | 570 | } |
529 | } | 571 | } |
530 | 572 | ||
531 | key = tsk->signal->process_keyring; | 573 | key = context->signal->process_keyring; |
532 | atomic_inc(&key->usage); | 574 | atomic_inc(&key->usage); |
533 | break; | 575 | break; |
534 | 576 | ||
535 | case KEY_SPEC_SESSION_KEYRING: | 577 | case KEY_SPEC_SESSION_KEYRING: |
536 | if (!tsk->signal->session_keyring) { | 578 | if (!context->signal->session_keyring) { |
537 | /* always install a session keyring upon access if one | 579 | /* always install a session keyring upon access if one |
538 | * doesn't exist yet */ | 580 | * doesn't exist yet */ |
539 | ret = install_session_keyring( | 581 | ret = install_session_keyring( |
540 | tsk, tsk->user->session_keyring); | 582 | context, context->user->session_keyring); |
541 | if (ret < 0) | 583 | if (ret < 0) |
542 | goto error; | 584 | goto error; |
543 | } | 585 | } |
544 | 586 | ||
545 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | 587 | rcu_read_lock(); |
546 | key = tsk->signal->session_keyring; | 588 | key = rcu_dereference(context->signal->session_keyring); |
547 | atomic_inc(&key->usage); | 589 | atomic_inc(&key->usage); |
548 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | 590 | rcu_read_unlock(); |
549 | break; | 591 | break; |
550 | 592 | ||
551 | case KEY_SPEC_USER_KEYRING: | 593 | case KEY_SPEC_USER_KEYRING: |
552 | key = tsk->user->uid_keyring; | 594 | key = context->user->uid_keyring; |
553 | atomic_inc(&key->usage); | 595 | atomic_inc(&key->usage); |
554 | break; | 596 | break; |
555 | 597 | ||
556 | case KEY_SPEC_USER_SESSION_KEYRING: | 598 | case KEY_SPEC_USER_SESSION_KEYRING: |
557 | key = tsk->user->session_keyring; | 599 | key = context->user->session_keyring; |
558 | atomic_inc(&key->usage); | 600 | atomic_inc(&key->usage); |
559 | break; | 601 | break; |
560 | 602 | ||
@@ -574,7 +616,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
574 | break; | 616 | break; |
575 | } | 617 | } |
576 | 618 | ||
577 | /* check the status and permissions */ | 619 | /* check the status */ |
578 | if (perm) { | 620 | if (perm) { |
579 | ret = key_validate(key); | 621 | ret = key_validate(key); |
580 | if (ret < 0) | 622 | if (ret < 0) |
@@ -585,8 +627,10 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
585 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 627 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
586 | goto invalid_key; | 628 | goto invalid_key; |
587 | 629 | ||
630 | /* check the permissions */ | ||
588 | ret = -EACCES; | 631 | ret = -EACCES; |
589 | if (!key_permission(key, perm)) | 632 | |
633 | if (!key_task_permission(key, context, perm)) | ||
590 | goto invalid_key; | 634 | goto invalid_key; |
591 | 635 | ||
592 | error: | 636 | error: |
@@ -609,7 +653,6 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
609 | long join_session_keyring(const char *name) | 653 | long join_session_keyring(const char *name) |
610 | { | 654 | { |
611 | struct task_struct *tsk = current; | 655 | struct task_struct *tsk = current; |
612 | unsigned long flags; | ||
613 | struct key *keyring; | 656 | struct key *keyring; |
614 | long ret; | 657 | long ret; |
615 | 658 | ||
@@ -619,9 +662,9 @@ long join_session_keyring(const char *name) | |||
619 | if (ret < 0) | 662 | if (ret < 0) |
620 | goto error; | 663 | goto error; |
621 | 664 | ||
622 | spin_lock_irqsave(&tsk->sighand->siglock, flags); | 665 | rcu_read_lock(); |
623 | ret = tsk->signal->session_keyring->serial; | 666 | ret = rcu_dereference(tsk->signal->session_keyring)->serial; |
624 | spin_unlock_irqrestore(&tsk->sighand->siglock, flags); | 667 | rcu_read_unlock(); |
625 | goto error; | 668 | goto error; |
626 | } | 669 | } |
627 | 670 | ||