aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/key.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-09-13 08:06:29 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-10-07 23:19:48 -0400
commitcf7f601c067994f371ba77721d1e45fce61a4569 (patch)
tree4ff5a12ae84cf47a9815c3e3979341a66360cb31 /security/keys/key.c
parent9bb9c3be56834653878f766f471fa1c20e562f4c (diff)
KEYS: Add payload preparsing opportunity prior to key instantiate or update
Give the key type the opportunity to preparse the payload prior to the instantiation and update routines being called. This is done with the provision of two new key type operations: int (*preparse)(struct key_preparsed_payload *prep); void (*free_preparse)(struct key_preparsed_payload *prep); If the first operation is present, then it is called before key creation (in the add/update case) or before the key semaphore is taken (in the update and instantiate cases). The second operation is called to clean up if the first was called. preparse() is given the opportunity to fill in the following structure: struct key_preparsed_payload { char *description; void *type_data[2]; void *payload; const void *data; size_t datalen; size_t quotalen; }; Before the preparser is called, the first three fields will have been cleared, the payload pointer and size will be stored in data and datalen and the default quota size from the key_type struct will be stored into quotalen. The preparser may parse the payload in any way it likes and may store data in the type_data[] and payload fields for use by the instantiate() and update() ops. The preparser may also propose a description for the key by attaching it as a string to the description field. This can be used by passing a NULL or "" description to the add_key() system call or the key_create_or_update() function. This cannot work with request_key() as that required the description to tell the upcall about the key to be created. This, for example permits keys that store PGP public keys to generate their own name from the user ID and public key fingerprint in the key. The instantiate() and update() operations are then modified to look like this: int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); int (*update)(struct key *key, struct key_preparsed_payload *prep); and the new payload data is passed in *prep, whether or not it was preparsed. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r--security/keys/key.c114
1 files changed, 82 insertions, 32 deletions
diff --git a/security/keys/key.c b/security/keys/key.c
index 50d96d4e06f2..1d039af99f50 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve);
412 * key_construction_mutex. 412 * key_construction_mutex.
413 */ 413 */
414static int __key_instantiate_and_link(struct key *key, 414static int __key_instantiate_and_link(struct key *key,
415 const void *data, 415 struct key_preparsed_payload *prep,
416 size_t datalen,
417 struct key *keyring, 416 struct key *keyring,
418 struct key *authkey, 417 struct key *authkey,
419 unsigned long *_prealloc) 418 unsigned long *_prealloc)
@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key,
431 /* can't instantiate twice */ 430 /* can't instantiate twice */
432 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { 431 if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
433 /* instantiate the key */ 432 /* instantiate the key */
434 ret = key->type->instantiate(key, data, datalen); 433 ret = key->type->instantiate(key, prep);
435 434
436 if (ret == 0) { 435 if (ret == 0) {
437 /* mark the key as being instantiated */ 436 /* mark the key as being instantiated */
@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key,
482 struct key *keyring, 481 struct key *keyring,
483 struct key *authkey) 482 struct key *authkey)
484{ 483{
484 struct key_preparsed_payload prep;
485 unsigned long prealloc; 485 unsigned long prealloc;
486 int ret; 486 int ret;
487 487
488 memset(&prep, 0, sizeof(prep));
489 prep.data = data;
490 prep.datalen = datalen;
491 prep.quotalen = key->type->def_datalen;
492 if (key->type->preparse) {
493 ret = key->type->preparse(&prep);
494 if (ret < 0)
495 goto error;
496 }
497
488 if (keyring) { 498 if (keyring) {
489 ret = __key_link_begin(keyring, key->type, key->description, 499 ret = __key_link_begin(keyring, key->type, key->description,
490 &prealloc); 500 &prealloc);
491 if (ret < 0) 501 if (ret < 0)
492 return ret; 502 goto error_free_preparse;
493 } 503 }
494 504
495 ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, 505 ret = __key_instantiate_and_link(key, &prep, keyring, authkey,
496 &prealloc); 506 &prealloc);
497 507
498 if (keyring) 508 if (keyring)
499 __key_link_end(keyring, key->type, prealloc); 509 __key_link_end(keyring, key->type, prealloc);
500 510
511error_free_preparse:
512 if (key->type->preparse)
513 key->type->free_preparse(&prep);
514error:
501 return ret; 515 return ret;
502} 516}
503 517
@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype)
706 * if we get an error. 720 * if we get an error.
707 */ 721 */
708static inline key_ref_t __key_update(key_ref_t key_ref, 722static inline key_ref_t __key_update(key_ref_t key_ref,
709 const void *payload, size_t plen) 723 struct key_preparsed_payload *prep)
710{ 724{
711 struct key *key = key_ref_to_ptr(key_ref); 725 struct key *key = key_ref_to_ptr(key_ref);
712 int ret; 726 int ret;
@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
722 736
723 down_write(&key->sem); 737 down_write(&key->sem);
724 738
725 ret = key->type->update(key, payload, plen); 739 ret = key->type->update(key, prep);
726 if (ret == 0) 740 if (ret == 0)
727 /* updating a negative key instantiates it */ 741 /* updating a negative key instantiates it */
728 clear_bit(KEY_FLAG_NEGATIVE, &key->flags); 742 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
774 unsigned long flags) 788 unsigned long flags)
775{ 789{
776 unsigned long prealloc; 790 unsigned long prealloc;
791 struct key_preparsed_payload prep;
777 const struct cred *cred = current_cred(); 792 const struct cred *cred = current_cred();
778 struct key_type *ktype; 793 struct key_type *ktype;
779 struct key *keyring, *key = NULL; 794 struct key *keyring, *key = NULL;
@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
789 } 804 }
790 805
791 key_ref = ERR_PTR(-EINVAL); 806 key_ref = ERR_PTR(-EINVAL);
792 if (!ktype->match || !ktype->instantiate) 807 if (!ktype->match || !ktype->instantiate ||
793 goto error_2; 808 (!description && !ktype->preparse))
809 goto error_put_type;
794 810
795 keyring = key_ref_to_ptr(keyring_ref); 811 keyring = key_ref_to_ptr(keyring_ref);
796 812
@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
798 814
799 key_ref = ERR_PTR(-ENOTDIR); 815 key_ref = ERR_PTR(-ENOTDIR);
800 if (keyring->type != &key_type_keyring) 816 if (keyring->type != &key_type_keyring)
801 goto error_2; 817 goto error_put_type;
818
819 memset(&prep, 0, sizeof(prep));
820 prep.data = payload;
821 prep.datalen = plen;
822 prep.quotalen = ktype->def_datalen;
823 if (ktype->preparse) {
824 ret = ktype->preparse(&prep);
825 if (ret < 0) {
826 key_ref = ERR_PTR(ret);
827 goto error_put_type;
828 }
829 if (!description)
830 description = prep.description;
831 key_ref = ERR_PTR(-EINVAL);
832 if (!description)
833 goto error_free_prep;
834 }
802 835
803 ret = __key_link_begin(keyring, ktype, description, &prealloc); 836 ret = __key_link_begin(keyring, ktype, description, &prealloc);
804 if (ret < 0) 837 if (ret < 0) {
805 goto error_2; 838 key_ref = ERR_PTR(ret);
839 goto error_free_prep;
840 }
806 841
807 /* if we're going to allocate a new key, we're going to have 842 /* if we're going to allocate a new key, we're going to have
808 * to modify the keyring */ 843 * to modify the keyring */
809 ret = key_permission(keyring_ref, KEY_WRITE); 844 ret = key_permission(keyring_ref, KEY_WRITE);
810 if (ret < 0) { 845 if (ret < 0) {
811 key_ref = ERR_PTR(ret); 846 key_ref = ERR_PTR(ret);
812 goto error_3; 847 goto error_link_end;
813 } 848 }
814 849
815 /* if it's possible to update this type of key, search for an existing 850 /* if it's possible to update this type of key, search for an existing
@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
840 perm, flags); 875 perm, flags);
841 if (IS_ERR(key)) { 876 if (IS_ERR(key)) {
842 key_ref = ERR_CAST(key); 877 key_ref = ERR_CAST(key);
843 goto error_3; 878 goto error_link_end;
844 } 879 }
845 880
846 /* instantiate it and link it into the target keyring */ 881 /* instantiate it and link it into the target keyring */
847 ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, 882 ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc);
848 &prealloc);
849 if (ret < 0) { 883 if (ret < 0) {
850 key_put(key); 884 key_put(key);
851 key_ref = ERR_PTR(ret); 885 key_ref = ERR_PTR(ret);
852 goto error_3; 886 goto error_link_end;
853 } 887 }
854 888
855 key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); 889 key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
856 890
857 error_3: 891error_link_end:
858 __key_link_end(keyring, ktype, prealloc); 892 __key_link_end(keyring, ktype, prealloc);
859 error_2: 893error_free_prep:
894 if (ktype->preparse)
895 ktype->free_preparse(&prep);
896error_put_type:
860 key_type_put(ktype); 897 key_type_put(ktype);
861 error: 898error:
862 return key_ref; 899 return key_ref;
863 900
864 found_matching_key: 901 found_matching_key:
@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
866 * - we can drop the locks first as we have the key pinned 903 * - we can drop the locks first as we have the key pinned
867 */ 904 */
868 __key_link_end(keyring, ktype, prealloc); 905 __key_link_end(keyring, ktype, prealloc);
869 key_type_put(ktype);
870 906
871 key_ref = __key_update(key_ref, payload, plen); 907 key_ref = __key_update(key_ref, &prep);
872 goto error; 908 goto error_free_prep;
873} 909}
874EXPORT_SYMBOL(key_create_or_update); 910EXPORT_SYMBOL(key_create_or_update);
875 911
@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update);
888 */ 924 */
889int key_update(key_ref_t key_ref, const void *payload, size_t plen) 925int key_update(key_ref_t key_ref, const void *payload, size_t plen)
890{ 926{
927 struct key_preparsed_payload prep;
891 struct key *key = key_ref_to_ptr(key_ref); 928 struct key *key = key_ref_to_ptr(key_ref);
892 int ret; 929 int ret;
893 930
@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
900 937
901 /* attempt to update it if supported */ 938 /* attempt to update it if supported */
902 ret = -EOPNOTSUPP; 939 ret = -EOPNOTSUPP;
903 if (key->type->update) { 940 if (!key->type->update)
904 down_write(&key->sem); 941 goto error;
905
906 ret = key->type->update(key, payload, plen);
907 if (ret == 0)
908 /* updating a negative key instantiates it */
909 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
910 942
911 up_write(&key->sem); 943 memset(&prep, 0, sizeof(prep));
944 prep.data = payload;
945 prep.datalen = plen;
946 prep.quotalen = key->type->def_datalen;
947 if (key->type->preparse) {
948 ret = key->type->preparse(&prep);
949 if (ret < 0)
950 goto error;
912 } 951 }
913 952
914 error: 953 down_write(&key->sem);
954
955 ret = key->type->update(key, &prep);
956 if (ret == 0)
957 /* updating a negative key instantiates it */
958 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
959
960 up_write(&key->sem);
961
962 if (key->type->preparse)
963 key->type->free_preparse(&prep);
964error:
915 return ret; 965 return ret;
916} 966}
917EXPORT_SYMBOL(key_update); 967EXPORT_SYMBOL(key_update);