aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2010-04-30 09:32:39 -0400
committerJames Morris <jmorris@namei.org>2010-05-06 08:25:02 -0400
commitf70e2e06196ad4c1c762037da2f75354f6c16b81 (patch)
tree9632a1e655efb684c87f8c7be6d091fbb1a430e7 /security/keys/keyring.c
parent043b4d40f53131c5f72eca2a46555fe35328a930 (diff)
KEYS: Do preallocation for __key_link()
Do preallocation for __key_link() so that the various callers in request_key.c can deal with any errors from this source before attempting to construct a key. This allows them to assume that the actual linkage step is guaranteed to be successful. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c242
1 files changed, 145 insertions, 97 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 3f425a65906f..ef03a82a0135 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -660,20 +660,6 @@ cycle_detected:
660 660
661} /* end keyring_detect_cycle() */ 661} /* end keyring_detect_cycle() */
662 662
663/*****************************************************************************/
664/*
665 * dispose of a keyring list after the RCU grace period
666 */
667static void keyring_link_rcu_disposal(struct rcu_head *rcu)
668{
669 struct keyring_list *klist =
670 container_of(rcu, struct keyring_list, rcu);
671
672 kfree(klist);
673
674} /* end keyring_link_rcu_disposal() */
675
676/*****************************************************************************/
677/* 663/*
678 * dispose of a keyring list after the RCU grace period, freeing the unlinked 664 * dispose of a keyring list after the RCU grace period, freeing the unlinked
679 * key 665 * key
@@ -683,56 +669,51 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
683 struct keyring_list *klist = 669 struct keyring_list *klist =
684 container_of(rcu, struct keyring_list, rcu); 670 container_of(rcu, struct keyring_list, rcu);
685 671
686 key_put(klist->keys[klist->delkey]); 672 if (klist->delkey != USHORT_MAX)
673 key_put(klist->keys[klist->delkey]);
687 kfree(klist); 674 kfree(klist);
675}
688 676
689} /* end keyring_unlink_rcu_disposal() */
690
691/*****************************************************************************/
692/* 677/*
693 * link a key into to a keyring 678 * preallocate memory so that a key can be linked into to a keyring
694 * - must be called with the keyring's semaphore write-locked
695 * - discard already extant link to matching key if there is one
696 */ 679 */
697int __key_link(struct key *keyring, struct key *key) 680int __key_link_begin(struct key *keyring, const struct key_type *type,
681 const char *description,
682 struct keyring_list **_prealloc)
683 __acquires(&keyring->sem)
698{ 684{
699 struct keyring_list *klist, *nklist; 685 struct keyring_list *klist, *nklist;
700 unsigned max; 686 unsigned max;
701 size_t size; 687 size_t size;
702 int loop, ret; 688 int loop, ret;
703 689
704 ret = -EKEYREVOKED; 690 kenter("%d,%s,%s,", key_serial(keyring), type->name, description);
705 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
706 goto error;
707 691
708 ret = -ENOTDIR;
709 if (keyring->type != &key_type_keyring) 692 if (keyring->type != &key_type_keyring)
710 goto error; 693 return -ENOTDIR;
694
695 down_write(&keyring->sem);
696
697 ret = -EKEYREVOKED;
698 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
699 goto error_krsem;
711 700
712 /* do some special keyring->keyring link checks */ 701 /* serialise link/link calls to prevent parallel calls causing a cycle
713 if (key->type == &key_type_keyring) { 702 * when linking two keyring in opposite orders */
714 /* serialise link/link calls to prevent parallel calls causing 703 if (type == &key_type_keyring)
715 * a cycle when applied to two keyring in opposite orders */
716 down_write(&keyring_serialise_link_sem); 704 down_write(&keyring_serialise_link_sem);
717 705
718 /* check that we aren't going to create a cycle adding one 706 klist = rcu_dereference_locked_keyring(keyring);
719 * keyring to another */
720 ret = keyring_detect_cycle(keyring, key);
721 if (ret < 0)
722 goto error2;
723 }
724 707
725 /* see if there's a matching key we can displace */ 708 /* see if there's a matching key we can displace */
726 klist = rcu_dereference_locked_keyring(keyring);
727 if (klist && klist->nkeys > 0) { 709 if (klist && klist->nkeys > 0) {
728 struct key_type *type = key->type;
729
730 for (loop = klist->nkeys - 1; loop >= 0; loop--) { 710 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
731 if (klist->keys[loop]->type == type && 711 if (klist->keys[loop]->type == type &&
732 strcmp(klist->keys[loop]->description, 712 strcmp(klist->keys[loop]->description,
733 key->description) == 0 713 description) == 0
734 ) { 714 ) {
735 /* found a match - replace with new key */ 715 /* found a match - we'll replace this one with
716 * the new key */
736 size = sizeof(struct key *) * klist->maxkeys; 717 size = sizeof(struct key *) * klist->maxkeys;
737 size += sizeof(*klist); 718 size += sizeof(*klist);
738 BUG_ON(size > PAGE_SIZE); 719 BUG_ON(size > PAGE_SIZE);
@@ -740,22 +721,10 @@ int __key_link(struct key *keyring, struct key *key)
740 ret = -ENOMEM; 721 ret = -ENOMEM;
741 nklist = kmemdup(klist, size, GFP_KERNEL); 722 nklist = kmemdup(klist, size, GFP_KERNEL);
742 if (!nklist) 723 if (!nklist)
743 goto error2; 724 goto error_sem;
744
745 /* replace matched key */
746 atomic_inc(&key->usage);
747 nklist->keys[loop] = key;
748
749 rcu_assign_pointer(
750 keyring->payload.subscriptions,
751 nklist);
752
753 /* dispose of the old keyring list and the
754 * displaced key */
755 klist->delkey = loop;
756 call_rcu(&klist->rcu,
757 keyring_unlink_rcu_disposal);
758 725
726 /* note replacement slot */
727 klist->delkey = nklist->delkey = loop;
759 goto done; 728 goto done;
760 } 729 }
761 } 730 }
@@ -765,16 +734,11 @@ int __key_link(struct key *keyring, struct key *key)
765 ret = key_payload_reserve(keyring, 734 ret = key_payload_reserve(keyring,
766 keyring->datalen + KEYQUOTA_LINK_BYTES); 735 keyring->datalen + KEYQUOTA_LINK_BYTES);
767 if (ret < 0) 736 if (ret < 0)
768 goto error2; 737 goto error_sem;
769 738
770 if (klist && klist->nkeys < klist->maxkeys) { 739 if (klist && klist->nkeys < klist->maxkeys) {
771 /* there's sufficient slack space to add directly */ 740 /* there's sufficient slack space to append directly */
772 atomic_inc(&key->usage); 741 nklist = NULL;
773
774 klist->keys[klist->nkeys] = key;
775 smp_wmb();
776 klist->nkeys++;
777 smp_wmb();
778 } else { 742 } else {
779 /* grow the key list */ 743 /* grow the key list */
780 max = 4; 744 max = 4;
@@ -782,71 +746,155 @@ int __key_link(struct key *keyring, struct key *key)
782 max += klist->maxkeys; 746 max += klist->maxkeys;
783 747
784 ret = -ENFILE; 748 ret = -ENFILE;
785 if (max > 65535) 749 if (max > USHORT_MAX - 1)
786 goto error3; 750 goto error_quota;
787 size = sizeof(*klist) + sizeof(struct key *) * max; 751 size = sizeof(*klist) + sizeof(struct key *) * max;
788 if (size > PAGE_SIZE) 752 if (size > PAGE_SIZE)
789 goto error3; 753 goto error_quota;
790 754
791 ret = -ENOMEM; 755 ret = -ENOMEM;
792 nklist = kmalloc(size, GFP_KERNEL); 756 nklist = kmalloc(size, GFP_KERNEL);
793 if (!nklist) 757 if (!nklist)
794 goto error3; 758 goto error_quota;
795 nklist->maxkeys = max;
796 nklist->nkeys = 0;
797 759
760 nklist->maxkeys = max;
798 if (klist) { 761 if (klist) {
799 nklist->nkeys = klist->nkeys; 762 memcpy(nklist->keys, klist->keys,
800 memcpy(nklist->keys,
801 klist->keys,
802 sizeof(struct key *) * klist->nkeys); 763 sizeof(struct key *) * klist->nkeys);
764 nklist->delkey = klist->nkeys;
765 nklist->nkeys = klist->nkeys + 1;
766 klist->delkey = USHORT_MAX;
767 } else {
768 nklist->nkeys = 1;
769 nklist->delkey = 0;
803 } 770 }
804 771
805 /* add the key into the new space */ 772 /* add the key into the new space */
806 atomic_inc(&key->usage); 773 nklist->keys[nklist->delkey] = NULL;
807 nklist->keys[nklist->nkeys++] = key;
808
809 rcu_assign_pointer(keyring->payload.subscriptions, nklist);
810
811 /* dispose of the old keyring list */
812 if (klist)
813 call_rcu(&klist->rcu, keyring_link_rcu_disposal);
814 } 774 }
815 775
816done: 776done:
817 ret = 0; 777 *_prealloc = nklist;
818error2: 778 kleave(" = 0");
819 if (key->type == &key_type_keyring) 779 return 0;
820 up_write(&keyring_serialise_link_sem);
821error:
822 return ret;
823 780
824error3: 781error_quota:
825 /* undo the quota changes */ 782 /* undo the quota changes */
826 key_payload_reserve(keyring, 783 key_payload_reserve(keyring,
827 keyring->datalen - KEYQUOTA_LINK_BYTES); 784 keyring->datalen - KEYQUOTA_LINK_BYTES);
828 goto error2; 785error_sem:
786 if (type == &key_type_keyring)
787 up_write(&keyring_serialise_link_sem);
788error_krsem:
789 up_write(&keyring->sem);
790 kleave(" = %d", ret);
791 return ret;
792}
829 793
830} /* end __key_link() */ 794/*
795 * check already instantiated keys aren't going to be a problem
796 * - the caller must have called __key_link_begin()
797 * - don't need to call this for keys that were created since __key_link_begin()
798 * was called
799 */
800int __key_link_check_live_key(struct key *keyring, struct key *key)
801{
802 if (key->type == &key_type_keyring)
803 /* check that we aren't going to create a cycle by linking one
804 * keyring to another */
805 return keyring_detect_cycle(keyring, key);
806 return 0;
807}
808
809/*
810 * link a key into to a keyring
811 * - must be called with __key_link_begin() having being called
812 * - discard already extant link to matching key if there is one
813 */
814void __key_link(struct key *keyring, struct key *key,
815 struct keyring_list **_prealloc)
816{
817 struct keyring_list *klist, *nklist;
818
819 nklist = *_prealloc;
820 *_prealloc = NULL;
821
822 kenter("%d,%d,%p", keyring->serial, key->serial, nklist);
823
824 klist = rcu_dereference_protected(keyring->payload.subscriptions,
825 rwsem_is_locked(&keyring->sem));
826
827 atomic_inc(&key->usage);
828
829 /* there's a matching key we can displace or an empty slot in a newly
830 * allocated list we can fill */
831 if (nklist) {
832 kdebug("replace %hu/%hu/%hu",
833 nklist->delkey, nklist->nkeys, nklist->maxkeys);
834
835 nklist->keys[nklist->delkey] = key;
836
837 rcu_assign_pointer(keyring->payload.subscriptions, nklist);
838
839 /* dispose of the old keyring list and, if there was one, the
840 * displaced key */
841 if (klist) {
842 kdebug("dispose %hu/%hu/%hu",
843 klist->delkey, klist->nkeys, klist->maxkeys);
844 call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
845 }
846 } else {
847 /* there's sufficient slack space to append directly */
848 klist->keys[klist->nkeys] = key;
849 smp_wmb();
850 klist->nkeys++;
851 }
852}
853
854/*
855 * finish linking a key into to a keyring
856 * - must be called with __key_link_begin() having being called
857 */
858void __key_link_end(struct key *keyring, struct key_type *type,
859 struct keyring_list *prealloc)
860 __releases(&keyring->sem)
861{
862 BUG_ON(type == NULL);
863 BUG_ON(type->name == NULL);
864 kenter("%d,%s,%p", keyring->serial, type->name, prealloc);
865
866 if (type == &key_type_keyring)
867 up_write(&keyring_serialise_link_sem);
868
869 if (prealloc) {
870 kfree(prealloc);
871 key_payload_reserve(keyring,
872 keyring->datalen - KEYQUOTA_LINK_BYTES);
873 }
874 up_write(&keyring->sem);
875}
831 876
832/*****************************************************************************/
833/* 877/*
834 * link a key to a keyring 878 * link a key to a keyring
835 */ 879 */
836int key_link(struct key *keyring, struct key *key) 880int key_link(struct key *keyring, struct key *key)
837{ 881{
882 struct keyring_list *prealloc;
838 int ret; 883 int ret;
839 884
840 key_check(keyring); 885 key_check(keyring);
841 key_check(key); 886 key_check(key);
842 887
843 down_write(&keyring->sem); 888 ret = __key_link_begin(keyring, key->type, key->description, &prealloc);
844 ret = __key_link(keyring, key); 889 if (ret == 0) {
845 up_write(&keyring->sem); 890 ret = __key_link_check_live_key(keyring, key);
891 if (ret == 0)
892 __key_link(keyring, key, &prealloc);
893 __key_link_end(keyring, key->type, prealloc);
894 }
846 895
847 return ret; 896 return ret;
848 897}
849} /* end key_link() */
850 898
851EXPORT_SYMBOL(key_link); 899EXPORT_SYMBOL(key_link);
852 900