diff options
author | David Howells <dhowells@redhat.com> | 2014-07-18 13:56:36 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-07-22 16:46:41 -0400 |
commit | 8a7a3eb4ddbe7c7e639170a64adede7cbd5a9247 (patch) | |
tree | 47bcf8f2a0b98fba79953dc9a1fac719381a8bfa /net/rxrpc | |
parent | d46d494214cabfd03eb836e3a8ff3768d4c51497 (diff) |
KEYS: RxRPC: Use key preparsing
Make use of key preparsing in the RxRPC protocol so that quota size
determination can take place prior to keyring locking when a key is being
added.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'net/rxrpc')
-rw-r--r-- | net/rxrpc/ar-key.c | 165 |
1 files changed, 97 insertions, 68 deletions
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 0ad080790a32..3907add75932 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -26,8 +26,10 @@ | |||
26 | #include "ar-internal.h" | 26 | #include "ar-internal.h" |
27 | 27 | ||
28 | static int rxrpc_vet_description_s(const char *); | 28 | static int rxrpc_vet_description_s(const char *); |
29 | static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); | 29 | static int rxrpc_preparse(struct key_preparsed_payload *); |
30 | static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); | 30 | static int rxrpc_preparse_s(struct key_preparsed_payload *); |
31 | static void rxrpc_free_preparse(struct key_preparsed_payload *); | ||
32 | static void rxrpc_free_preparse_s(struct key_preparsed_payload *); | ||
31 | static void rxrpc_destroy(struct key *); | 33 | static void rxrpc_destroy(struct key *); |
32 | static void rxrpc_destroy_s(struct key *); | 34 | static void rxrpc_destroy_s(struct key *); |
33 | static void rxrpc_describe(const struct key *, struct seq_file *); | 35 | static void rxrpc_describe(const struct key *, struct seq_file *); |
@@ -39,7 +41,9 @@ static long rxrpc_read(const struct key *, char __user *, size_t); | |||
39 | */ | 41 | */ |
40 | struct key_type key_type_rxrpc = { | 42 | struct key_type key_type_rxrpc = { |
41 | .name = "rxrpc", | 43 | .name = "rxrpc", |
42 | .instantiate = rxrpc_instantiate, | 44 | .preparse = rxrpc_preparse, |
45 | .free_preparse = rxrpc_free_preparse, | ||
46 | .instantiate = generic_key_instantiate, | ||
43 | .match = user_match, | 47 | .match = user_match, |
44 | .destroy = rxrpc_destroy, | 48 | .destroy = rxrpc_destroy, |
45 | .describe = rxrpc_describe, | 49 | .describe = rxrpc_describe, |
@@ -54,7 +58,9 @@ EXPORT_SYMBOL(key_type_rxrpc); | |||
54 | struct key_type key_type_rxrpc_s = { | 58 | struct key_type key_type_rxrpc_s = { |
55 | .name = "rxrpc_s", | 59 | .name = "rxrpc_s", |
56 | .vet_description = rxrpc_vet_description_s, | 60 | .vet_description = rxrpc_vet_description_s, |
57 | .instantiate = rxrpc_instantiate_s, | 61 | .preparse = rxrpc_preparse_s, |
62 | .free_preparse = rxrpc_free_preparse_s, | ||
63 | .instantiate = generic_key_instantiate, | ||
58 | .match = user_match, | 64 | .match = user_match, |
59 | .destroy = rxrpc_destroy_s, | 65 | .destroy = rxrpc_destroy_s, |
60 | .describe = rxrpc_describe, | 66 | .describe = rxrpc_describe, |
@@ -81,13 +87,13 @@ static int rxrpc_vet_description_s(const char *desc) | |||
81 | * parse an RxKAD type XDR format token | 87 | * parse an RxKAD type XDR format token |
82 | * - the caller guarantees we have at least 4 words | 88 | * - the caller guarantees we have at least 4 words |
83 | */ | 89 | */ |
84 | static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, | 90 | static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep, |
85 | unsigned int toklen) | 91 | size_t datalen, |
92 | const __be32 *xdr, unsigned int toklen) | ||
86 | { | 93 | { |
87 | struct rxrpc_key_token *token, **pptoken; | 94 | struct rxrpc_key_token *token, **pptoken; |
88 | size_t plen; | 95 | size_t plen; |
89 | u32 tktlen; | 96 | u32 tktlen; |
90 | int ret; | ||
91 | 97 | ||
92 | _enter(",{%x,%x,%x,%x},%u", | 98 | _enter(",{%x,%x,%x,%x},%u", |
93 | ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), | 99 | ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), |
@@ -103,9 +109,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, | |||
103 | return -EKEYREJECTED; | 109 | return -EKEYREJECTED; |
104 | 110 | ||
105 | plen = sizeof(*token) + sizeof(*token->kad) + tktlen; | 111 | plen = sizeof(*token) + sizeof(*token->kad) + tktlen; |
106 | ret = key_payload_reserve(key, key->datalen + plen); | 112 | prep->quotalen = datalen + plen; |
107 | if (ret < 0) | ||
108 | return ret; | ||
109 | 113 | ||
110 | plen -= sizeof(*token); | 114 | plen -= sizeof(*token); |
111 | token = kzalloc(sizeof(*token), GFP_KERNEL); | 115 | token = kzalloc(sizeof(*token), GFP_KERNEL); |
@@ -146,16 +150,16 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, | |||
146 | token->kad->ticket[6], token->kad->ticket[7]); | 150 | token->kad->ticket[6], token->kad->ticket[7]); |
147 | 151 | ||
148 | /* count the number of tokens attached */ | 152 | /* count the number of tokens attached */ |
149 | key->type_data.x[0]++; | 153 | prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); |
150 | 154 | ||
151 | /* attach the data */ | 155 | /* attach the data */ |
152 | for (pptoken = (struct rxrpc_key_token **)&key->payload.data; | 156 | for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; |
153 | *pptoken; | 157 | *pptoken; |
154 | pptoken = &(*pptoken)->next) | 158 | pptoken = &(*pptoken)->next) |
155 | continue; | 159 | continue; |
156 | *pptoken = token; | 160 | *pptoken = token; |
157 | if (token->kad->expiry < key->expiry) | 161 | if (token->kad->expiry < prep->expiry) |
158 | key->expiry = token->kad->expiry; | 162 | prep->expiry = token->kad->expiry; |
159 | 163 | ||
160 | _leave(" = 0"); | 164 | _leave(" = 0"); |
161 | return 0; | 165 | return 0; |
@@ -418,8 +422,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, | |||
418 | * parse an RxK5 type XDR format token | 422 | * parse an RxK5 type XDR format token |
419 | * - the caller guarantees we have at least 4 words | 423 | * - the caller guarantees we have at least 4 words |
420 | */ | 424 | */ |
421 | static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, | 425 | static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep, |
422 | unsigned int toklen) | 426 | size_t datalen, |
427 | const __be32 *xdr, unsigned int toklen) | ||
423 | { | 428 | { |
424 | struct rxrpc_key_token *token, **pptoken; | 429 | struct rxrpc_key_token *token, **pptoken; |
425 | struct rxk5_key *rxk5; | 430 | struct rxk5_key *rxk5; |
@@ -432,9 +437,7 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, | |||
432 | 437 | ||
433 | /* reserve some payload space for this subkey - the length of the token | 438 | /* reserve some payload space for this subkey - the length of the token |
434 | * is a reasonable approximation */ | 439 | * is a reasonable approximation */ |
435 | ret = key_payload_reserve(key, key->datalen + toklen); | 440 | prep->quotalen = datalen + toklen; |
436 | if (ret < 0) | ||
437 | return ret; | ||
438 | 441 | ||
439 | token = kzalloc(sizeof(*token), GFP_KERNEL); | 442 | token = kzalloc(sizeof(*token), GFP_KERNEL); |
440 | if (!token) | 443 | if (!token) |
@@ -520,14 +523,14 @@ static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, | |||
520 | if (toklen != 0) | 523 | if (toklen != 0) |
521 | goto inval; | 524 | goto inval; |
522 | 525 | ||
523 | /* attach the payload to the key */ | 526 | /* attach the payload */ |
524 | for (pptoken = (struct rxrpc_key_token **)&key->payload.data; | 527 | for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; |
525 | *pptoken; | 528 | *pptoken; |
526 | pptoken = &(*pptoken)->next) | 529 | pptoken = &(*pptoken)->next) |
527 | continue; | 530 | continue; |
528 | *pptoken = token; | 531 | *pptoken = token; |
529 | if (token->kad->expiry < key->expiry) | 532 | if (token->kad->expiry < prep->expiry) |
530 | key->expiry = token->kad->expiry; | 533 | prep->expiry = token->kad->expiry; |
531 | 534 | ||
532 | _leave(" = 0"); | 535 | _leave(" = 0"); |
533 | return 0; | 536 | return 0; |
@@ -545,16 +548,17 @@ error: | |||
545 | * attempt to parse the data as the XDR format | 548 | * attempt to parse the data as the XDR format |
546 | * - the caller guarantees we have more than 7 words | 549 | * - the caller guarantees we have more than 7 words |
547 | */ | 550 | */ |
548 | static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen) | 551 | static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) |
549 | { | 552 | { |
550 | const __be32 *xdr = data, *token; | 553 | const __be32 *xdr = prep->data, *token; |
551 | const char *cp; | 554 | const char *cp; |
552 | unsigned int len, tmp, loop, ntoken, toklen, sec_ix; | 555 | unsigned int len, tmp, loop, ntoken, toklen, sec_ix; |
556 | size_t datalen = prep->datalen; | ||
553 | int ret; | 557 | int ret; |
554 | 558 | ||
555 | _enter(",{%x,%x,%x,%x},%zu", | 559 | _enter(",{%x,%x,%x,%x},%zu", |
556 | ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), | 560 | ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), |
557 | datalen); | 561 | prep->datalen); |
558 | 562 | ||
559 | if (datalen > AFSTOKEN_LENGTH_MAX) | 563 | if (datalen > AFSTOKEN_LENGTH_MAX) |
560 | goto not_xdr; | 564 | goto not_xdr; |
@@ -635,13 +639,13 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal | |||
635 | 639 | ||
636 | switch (sec_ix) { | 640 | switch (sec_ix) { |
637 | case RXRPC_SECURITY_RXKAD: | 641 | case RXRPC_SECURITY_RXKAD: |
638 | ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen); | 642 | ret = rxrpc_preparse_xdr_rxkad(prep, datalen, xdr, toklen); |
639 | if (ret != 0) | 643 | if (ret != 0) |
640 | goto error; | 644 | goto error; |
641 | break; | 645 | break; |
642 | 646 | ||
643 | case RXRPC_SECURITY_RXK5: | 647 | case RXRPC_SECURITY_RXK5: |
644 | ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen); | 648 | ret = rxrpc_preparse_xdr_rxk5(prep, datalen, xdr, toklen); |
645 | if (ret != 0) | 649 | if (ret != 0) |
646 | goto error; | 650 | goto error; |
647 | break; | 651 | break; |
@@ -665,8 +669,9 @@ error: | |||
665 | } | 669 | } |
666 | 670 | ||
667 | /* | 671 | /* |
668 | * instantiate an rxrpc defined key | 672 | * Preparse an rxrpc defined key. |
669 | * data should be of the form: | 673 | * |
674 | * Data should be of the form: | ||
670 | * OFFSET LEN CONTENT | 675 | * OFFSET LEN CONTENT |
671 | * 0 4 key interface version number | 676 | * 0 4 key interface version number |
672 | * 4 2 security index (type) | 677 | * 4 2 security index (type) |
@@ -678,7 +683,7 @@ error: | |||
678 | * | 683 | * |
679 | * if no data is provided, then a no-security key is made | 684 | * if no data is provided, then a no-security key is made |
680 | */ | 685 | */ |
681 | static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) | 686 | static int rxrpc_preparse(struct key_preparsed_payload *prep) |
682 | { | 687 | { |
683 | const struct rxrpc_key_data_v1 *v1; | 688 | const struct rxrpc_key_data_v1 *v1; |
684 | struct rxrpc_key_token *token, **pp; | 689 | struct rxrpc_key_token *token, **pp; |
@@ -686,7 +691,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep | |||
686 | u32 kver; | 691 | u32 kver; |
687 | int ret; | 692 | int ret; |
688 | 693 | ||
689 | _enter("{%x},,%zu", key_serial(key), prep->datalen); | 694 | _enter("%zu", prep->datalen); |
690 | 695 | ||
691 | /* handle a no-security key */ | 696 | /* handle a no-security key */ |
692 | if (!prep->data && prep->datalen == 0) | 697 | if (!prep->data && prep->datalen == 0) |
@@ -694,7 +699,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep | |||
694 | 699 | ||
695 | /* determine if the XDR payload format is being used */ | 700 | /* determine if the XDR payload format is being used */ |
696 | if (prep->datalen > 7 * 4) { | 701 | if (prep->datalen > 7 * 4) { |
697 | ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); | 702 | ret = rxrpc_preparse_xdr(prep); |
698 | if (ret != -EPROTO) | 703 | if (ret != -EPROTO) |
699 | return ret; | 704 | return ret; |
700 | } | 705 | } |
@@ -743,9 +748,7 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep | |||
743 | goto error; | 748 | goto error; |
744 | 749 | ||
745 | plen = sizeof(*token->kad) + v1->ticket_length; | 750 | plen = sizeof(*token->kad) + v1->ticket_length; |
746 | ret = key_payload_reserve(key, plen + sizeof(*token)); | 751 | prep->quotalen = plen + sizeof(*token); |
747 | if (ret < 0) | ||
748 | goto error; | ||
749 | 752 | ||
750 | ret = -ENOMEM; | 753 | ret = -ENOMEM; |
751 | token = kzalloc(sizeof(*token), GFP_KERNEL); | 754 | token = kzalloc(sizeof(*token), GFP_KERNEL); |
@@ -762,15 +765,16 @@ static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep | |||
762 | memcpy(&token->kad->session_key, &v1->session_key, 8); | 765 | memcpy(&token->kad->session_key, &v1->session_key, 8); |
763 | memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length); | 766 | memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length); |
764 | 767 | ||
765 | /* attach the data */ | 768 | /* count the number of tokens attached */ |
766 | key->type_data.x[0]++; | 769 | prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); |
767 | 770 | ||
768 | pp = (struct rxrpc_key_token **)&key->payload.data; | 771 | /* attach the data */ |
772 | pp = (struct rxrpc_key_token **)&prep->payload[0]; | ||
769 | while (*pp) | 773 | while (*pp) |
770 | pp = &(*pp)->next; | 774 | pp = &(*pp)->next; |
771 | *pp = token; | 775 | *pp = token; |
772 | if (token->kad->expiry < key->expiry) | 776 | if (token->kad->expiry < prep->expiry) |
773 | key->expiry = token->kad->expiry; | 777 | prep->expiry = token->kad->expiry; |
774 | token = NULL; | 778 | token = NULL; |
775 | ret = 0; | 779 | ret = 0; |
776 | 780 | ||
@@ -781,20 +785,55 @@ error: | |||
781 | } | 785 | } |
782 | 786 | ||
783 | /* | 787 | /* |
784 | * instantiate a server secret key | 788 | * Free token list. |
785 | * data should be a pointer to the 8-byte secret key | ||
786 | */ | 789 | */ |
787 | static int rxrpc_instantiate_s(struct key *key, | 790 | static void rxrpc_free_token_list(struct rxrpc_key_token *token) |
788 | struct key_preparsed_payload *prep) | 791 | { |
792 | struct rxrpc_key_token *next; | ||
793 | |||
794 | for (; token; token = next) { | ||
795 | next = token->next; | ||
796 | switch (token->security_index) { | ||
797 | case RXRPC_SECURITY_RXKAD: | ||
798 | kfree(token->kad); | ||
799 | break; | ||
800 | case RXRPC_SECURITY_RXK5: | ||
801 | if (token->k5) | ||
802 | rxrpc_rxk5_free(token->k5); | ||
803 | break; | ||
804 | default: | ||
805 | printk(KERN_ERR "Unknown token type %x on rxrpc key\n", | ||
806 | token->security_index); | ||
807 | BUG(); | ||
808 | } | ||
809 | |||
810 | kfree(token); | ||
811 | } | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * Clean up preparse data. | ||
816 | */ | ||
817 | static void rxrpc_free_preparse(struct key_preparsed_payload *prep) | ||
818 | { | ||
819 | rxrpc_free_token_list(prep->payload[0]); | ||
820 | } | ||
821 | |||
822 | /* | ||
823 | * Preparse a server secret key. | ||
824 | * | ||
825 | * The data should be the 8-byte secret key. | ||
826 | */ | ||
827 | static int rxrpc_preparse_s(struct key_preparsed_payload *prep) | ||
789 | { | 828 | { |
790 | struct crypto_blkcipher *ci; | 829 | struct crypto_blkcipher *ci; |
791 | 830 | ||
792 | _enter("{%x},,%zu", key_serial(key), prep->datalen); | 831 | _enter("%zu", prep->datalen); |
793 | 832 | ||
794 | if (prep->datalen != 8) | 833 | if (prep->datalen != 8) |
795 | return -EINVAL; | 834 | return -EINVAL; |
796 | 835 | ||
797 | memcpy(&key->type_data, prep->data, 8); | 836 | memcpy(&prep->type_data, prep->data, 8); |
798 | 837 | ||
799 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); | 838 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); |
800 | if (IS_ERR(ci)) { | 839 | if (IS_ERR(ci)) { |
@@ -805,36 +844,26 @@ static int rxrpc_instantiate_s(struct key *key, | |||
805 | if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) | 844 | if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) |
806 | BUG(); | 845 | BUG(); |
807 | 846 | ||
808 | key->payload.data = ci; | 847 | prep->payload[0] = ci; |
809 | _leave(" = 0"); | 848 | _leave(" = 0"); |
810 | return 0; | 849 | return 0; |
811 | } | 850 | } |
812 | 851 | ||
813 | /* | 852 | /* |
853 | * Clean up preparse data. | ||
854 | */ | ||
855 | static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) | ||
856 | { | ||
857 | if (prep->payload[0]) | ||
858 | crypto_free_blkcipher(prep->payload[0]); | ||
859 | } | ||
860 | |||
861 | /* | ||
814 | * dispose of the data dangling from the corpse of a rxrpc key | 862 | * dispose of the data dangling from the corpse of a rxrpc key |
815 | */ | 863 | */ |
816 | static void rxrpc_destroy(struct key *key) | 864 | static void rxrpc_destroy(struct key *key) |
817 | { | 865 | { |
818 | struct rxrpc_key_token *token; | 866 | rxrpc_free_token_list(key->payload.data); |
819 | |||
820 | while ((token = key->payload.data)) { | ||
821 | key->payload.data = token->next; | ||
822 | switch (token->security_index) { | ||
823 | case RXRPC_SECURITY_RXKAD: | ||
824 | kfree(token->kad); | ||
825 | break; | ||
826 | case RXRPC_SECURITY_RXK5: | ||
827 | if (token->k5) | ||
828 | rxrpc_rxk5_free(token->k5); | ||
829 | break; | ||
830 | default: | ||
831 | printk(KERN_ERR "Unknown token type %x on rxrpc key\n", | ||
832 | token->security_index); | ||
833 | BUG(); | ||
834 | } | ||
835 | |||
836 | kfree(token); | ||
837 | } | ||
838 | } | 867 | } |
839 | 868 | ||
840 | /* | 869 | /* |