aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c132
1 files changed, 64 insertions, 68 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5d22c0388b32..d65a180f888d 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -481,51 +481,6 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
481 481
482/*****************************************************************************/ 482/*****************************************************************************/
483/* 483/*
484 * search for an instantiation authorisation key matching a target key
485 * - the RCU read lock must be held by the caller
486 * - a target_id of zero specifies any valid token
487 */
488struct key *keyring_search_instkey(struct key *keyring,
489 key_serial_t target_id)
490{
491 struct request_key_auth *rka;
492 struct keyring_list *klist;
493 struct key *instkey;
494 int loop;
495
496 klist = rcu_dereference(keyring->payload.subscriptions);
497 if (klist) {
498 for (loop = 0; loop < klist->nkeys; loop++) {
499 instkey = klist->keys[loop];
500
501 if (instkey->type != &key_type_request_key_auth)
502 continue;
503
504 rka = instkey->payload.data;
505 if (target_id && rka->target_key->serial != target_id)
506 continue;
507
508 /* the auth key is revoked during instantiation */
509 if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
510 goto found;
511
512 instkey = ERR_PTR(-EKEYREVOKED);
513 goto error;
514 }
515 }
516
517 instkey = ERR_PTR(-EACCES);
518 goto error;
519
520found:
521 atomic_inc(&instkey->usage);
522error:
523 return instkey;
524
525} /* end keyring_search_instkey() */
526
527/*****************************************************************************/
528/*
529 * find a keyring with the specified name 484 * find a keyring with the specified name
530 * - all named keyrings are searched 485 * - all named keyrings are searched
531 * - only find keyrings with search permission for the process 486 * - only find keyrings with search permission for the process
@@ -684,15 +639,31 @@ static void keyring_link_rcu_disposal(struct rcu_head *rcu)
684 639
685/*****************************************************************************/ 640/*****************************************************************************/
686/* 641/*
642 * dispose of a keyring list after the RCU grace period, freeing the unlinked
643 * key
644 */
645static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
646{
647 struct keyring_list *klist =
648 container_of(rcu, struct keyring_list, rcu);
649
650 key_put(klist->keys[klist->delkey]);
651 kfree(klist);
652
653} /* end keyring_unlink_rcu_disposal() */
654
655/*****************************************************************************/
656/*
687 * link a key into to a keyring 657 * link a key into to a keyring
688 * - must be called with the keyring's semaphore write-locked 658 * - must be called with the keyring's semaphore write-locked
659 * - discard already extant link to matching key if there is one
689 */ 660 */
690int __key_link(struct key *keyring, struct key *key) 661int __key_link(struct key *keyring, struct key *key)
691{ 662{
692 struct keyring_list *klist, *nklist; 663 struct keyring_list *klist, *nklist;
693 unsigned max; 664 unsigned max;
694 size_t size; 665 size_t size;
695 int ret; 666 int loop, ret;
696 667
697 ret = -EKEYREVOKED; 668 ret = -EKEYREVOKED;
698 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 669 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -714,6 +685,48 @@ int __key_link(struct key *keyring, struct key *key)
714 goto error2; 685 goto error2;
715 } 686 }
716 687
688 /* see if there's a matching key we can displace */
689 klist = keyring->payload.subscriptions;
690
691 if (klist && klist->nkeys > 0) {
692 struct key_type *type = key->type;
693
694 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
695 if (klist->keys[loop]->type == type &&
696 strcmp(klist->keys[loop]->description,
697 key->description) == 0
698 ) {
699 /* found a match - replace with new key */
700 size = sizeof(struct key *) * klist->maxkeys;
701 size += sizeof(*klist);
702 BUG_ON(size > PAGE_SIZE);
703
704 ret = -ENOMEM;
705 nklist = kmalloc(size, GFP_KERNEL);
706 if (!nklist)
707 goto error2;
708
709 memcpy(nklist, klist, size);
710
711 /* replace matched key */
712 atomic_inc(&key->usage);
713 nklist->keys[loop] = key;
714
715 rcu_assign_pointer(
716 keyring->payload.subscriptions,
717 nklist);
718
719 /* dispose of the old keyring list and the
720 * displaced key */
721 klist->delkey = loop;
722 call_rcu(&klist->rcu,
723 keyring_unlink_rcu_disposal);
724
725 goto done;
726 }
727 }
728 }
729
717 /* check that we aren't going to overrun the user's quota */ 730 /* check that we aren't going to overrun the user's quota */
718 ret = key_payload_reserve(keyring, 731 ret = key_payload_reserve(keyring,
719 keyring->datalen + KEYQUOTA_LINK_BYTES); 732 keyring->datalen + KEYQUOTA_LINK_BYTES);
@@ -730,8 +743,6 @@ int __key_link(struct key *keyring, struct key *key)
730 smp_wmb(); 743 smp_wmb();
731 klist->nkeys++; 744 klist->nkeys++;
732 smp_wmb(); 745 smp_wmb();
733
734 ret = 0;
735 } 746 }
736 else { 747 else {
737 /* grow the key list */ 748 /* grow the key list */
@@ -769,16 +780,16 @@ int __key_link(struct key *keyring, struct key *key)
769 /* dispose of the old keyring list */ 780 /* dispose of the old keyring list */
770 if (klist) 781 if (klist)
771 call_rcu(&klist->rcu, keyring_link_rcu_disposal); 782 call_rcu(&klist->rcu, keyring_link_rcu_disposal);
772
773 ret = 0;
774 } 783 }
775 784
776 error2: 785done:
786 ret = 0;
787error2:
777 up_write(&keyring_serialise_link_sem); 788 up_write(&keyring_serialise_link_sem);
778 error: 789error:
779 return ret; 790 return ret;
780 791
781 error3: 792error3:
782 /* undo the quota changes */ 793 /* undo the quota changes */
783 key_payload_reserve(keyring, 794 key_payload_reserve(keyring,
784 keyring->datalen - KEYQUOTA_LINK_BYTES); 795 keyring->datalen - KEYQUOTA_LINK_BYTES);
@@ -809,21 +820,6 @@ EXPORT_SYMBOL(key_link);
809 820
810/*****************************************************************************/ 821/*****************************************************************************/
811/* 822/*
812 * dispose of a keyring list after the RCU grace period, freeing the unlinked
813 * key
814 */
815static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
816{
817 struct keyring_list *klist =
818 container_of(rcu, struct keyring_list, rcu);
819
820 key_put(klist->keys[klist->delkey]);
821 kfree(klist);
822
823} /* end keyring_unlink_rcu_disposal() */
824
825/*****************************************************************************/
826/*
827 * unlink the first link to a key from a keyring 823 * unlink the first link to a key from a keyring
828 */ 824 */
829int key_unlink(struct key *keyring, struct key *key) 825int key_unlink(struct key *keyring, struct key *key)