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.c87
1 files changed, 64 insertions, 23 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5d22c0388b32..09d92d52ef75 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -684,15 +684,31 @@ static void keyring_link_rcu_disposal(struct rcu_head *rcu)
684 684
685/*****************************************************************************/ 685/*****************************************************************************/
686/* 686/*
687 * dispose of a keyring list after the RCU grace period, freeing the unlinked
688 * key
689 */
690static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
691{
692 struct keyring_list *klist =
693 container_of(rcu, struct keyring_list, rcu);
694
695 key_put(klist->keys[klist->delkey]);
696 kfree(klist);
697
698} /* end keyring_unlink_rcu_disposal() */
699
700/*****************************************************************************/
701/*
687 * link a key into to a keyring 702 * link a key into to a keyring
688 * - must be called with the keyring's semaphore write-locked 703 * - must be called with the keyring's semaphore write-locked
704 * - discard already extant link to matching key if there is one
689 */ 705 */
690int __key_link(struct key *keyring, struct key *key) 706int __key_link(struct key *keyring, struct key *key)
691{ 707{
692 struct keyring_list *klist, *nklist; 708 struct keyring_list *klist, *nklist;
693 unsigned max; 709 unsigned max;
694 size_t size; 710 size_t size;
695 int ret; 711 int loop, ret;
696 712
697 ret = -EKEYREVOKED; 713 ret = -EKEYREVOKED;
698 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 714 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -714,6 +730,48 @@ int __key_link(struct key *keyring, struct key *key)
714 goto error2; 730 goto error2;
715 } 731 }
716 732
733 /* see if there's a matching key we can displace */
734 klist = keyring->payload.subscriptions;
735
736 if (klist && klist->nkeys > 0) {
737 struct key_type *type = key->type;
738
739 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
740 if (klist->keys[loop]->type == type &&
741 strcmp(klist->keys[loop]->description,
742 key->description) == 0
743 ) {
744 /* found a match - replace with new key */
745 size = sizeof(struct key *) * klist->maxkeys;
746 size += sizeof(*klist);
747 BUG_ON(size > PAGE_SIZE);
748
749 ret = -ENOMEM;
750 nklist = kmalloc(size, GFP_KERNEL);
751 if (!nklist)
752 goto error2;
753
754 memcpy(nklist, klist, size);
755
756 /* replace matched key */
757 atomic_inc(&key->usage);
758 nklist->keys[loop] = key;
759
760 rcu_assign_pointer(
761 keyring->payload.subscriptions,
762 nklist);
763
764 /* dispose of the old keyring list and the
765 * displaced key */
766 klist->delkey = loop;
767 call_rcu(&klist->rcu,
768 keyring_unlink_rcu_disposal);
769
770 goto done;
771 }
772 }
773 }
774
717 /* check that we aren't going to overrun the user's quota */ 775 /* check that we aren't going to overrun the user's quota */
718 ret = key_payload_reserve(keyring, 776 ret = key_payload_reserve(keyring,
719 keyring->datalen + KEYQUOTA_LINK_BYTES); 777 keyring->datalen + KEYQUOTA_LINK_BYTES);
@@ -730,8 +788,6 @@ int __key_link(struct key *keyring, struct key *key)
730 smp_wmb(); 788 smp_wmb();
731 klist->nkeys++; 789 klist->nkeys++;
732 smp_wmb(); 790 smp_wmb();
733
734 ret = 0;
735 } 791 }
736 else { 792 else {
737 /* grow the key list */ 793 /* grow the key list */
@@ -769,16 +825,16 @@ int __key_link(struct key *keyring, struct key *key)
769 /* dispose of the old keyring list */ 825 /* dispose of the old keyring list */
770 if (klist) 826 if (klist)
771 call_rcu(&klist->rcu, keyring_link_rcu_disposal); 827 call_rcu(&klist->rcu, keyring_link_rcu_disposal);
772
773 ret = 0;
774 } 828 }
775 829
776 error2: 830done:
831 ret = 0;
832error2:
777 up_write(&keyring_serialise_link_sem); 833 up_write(&keyring_serialise_link_sem);
778 error: 834error:
779 return ret; 835 return ret;
780 836
781 error3: 837error3:
782 /* undo the quota changes */ 838 /* undo the quota changes */
783 key_payload_reserve(keyring, 839 key_payload_reserve(keyring,
784 keyring->datalen - KEYQUOTA_LINK_BYTES); 840 keyring->datalen - KEYQUOTA_LINK_BYTES);
@@ -809,21 +865,6 @@ EXPORT_SYMBOL(key_link);
809 865
810/*****************************************************************************/ 866/*****************************************************************************/
811/* 867/*
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 868 * unlink the first link to a key from a keyring
828 */ 869 */
829int key_unlink(struct key *keyring, struct key *key) 870int key_unlink(struct key *keyring, struct key *key)