diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/rxrpc/ar-key.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index a3a7acb5071a..bf4d623ee1ce 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -29,6 +29,7 @@ static int rxrpc_instantiate_s(struct key *, const void *, size_t); | |||
29 | static void rxrpc_destroy(struct key *); | 29 | static void rxrpc_destroy(struct key *); |
30 | static void rxrpc_destroy_s(struct key *); | 30 | static void rxrpc_destroy_s(struct key *); |
31 | static void rxrpc_describe(const struct key *, struct seq_file *); | 31 | static void rxrpc_describe(const struct key *, struct seq_file *); |
32 | static long rxrpc_read(const struct key *, char __user *, size_t); | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * rxrpc defined keys take an arbitrary string as the description and an | 35 | * rxrpc defined keys take an arbitrary string as the description and an |
@@ -40,6 +41,7 @@ struct key_type key_type_rxrpc = { | |||
40 | .match = user_match, | 41 | .match = user_match, |
41 | .destroy = rxrpc_destroy, | 42 | .destroy = rxrpc_destroy, |
42 | .describe = rxrpc_describe, | 43 | .describe = rxrpc_describe, |
44 | .read = rxrpc_read, | ||
43 | }; | 45 | }; |
44 | EXPORT_SYMBOL(key_type_rxrpc); | 46 | EXPORT_SYMBOL(key_type_rxrpc); |
45 | 47 | ||
@@ -592,3 +594,110 @@ struct key *rxrpc_get_null_key(const char *keyname) | |||
592 | return key; | 594 | return key; |
593 | } | 595 | } |
594 | EXPORT_SYMBOL(rxrpc_get_null_key); | 596 | EXPORT_SYMBOL(rxrpc_get_null_key); |
597 | |||
598 | /* | ||
599 | * read the contents of an rxrpc key | ||
600 | * - this returns the result in XDR form | ||
601 | */ | ||
602 | static long rxrpc_read(const struct key *key, | ||
603 | char __user *buffer, size_t buflen) | ||
604 | { | ||
605 | struct rxrpc_key_token *token; | ||
606 | size_t size, toksize; | ||
607 | __be32 __user *xdr; | ||
608 | u32 cnlen, tktlen, ntoks, zero; | ||
609 | |||
610 | _enter(""); | ||
611 | |||
612 | /* we don't know what form we should return non-AFS keys in */ | ||
613 | if (memcmp(key->description, "afs@", 4) != 0) | ||
614 | return -EOPNOTSUPP; | ||
615 | cnlen = strlen(key->description + 4); | ||
616 | |||
617 | /* AFS keys we return in XDR form, so we need to work out the size of | ||
618 | * the XDR */ | ||
619 | size = 2 * 4; /* flags, cellname len */ | ||
620 | size += (cnlen + 3) & ~3; /* cellname */ | ||
621 | size += 1 * 4; /* token count */ | ||
622 | |||
623 | ntoks = 0; | ||
624 | for (token = key->payload.data; token; token = token->next) { | ||
625 | switch (token->security_index) { | ||
626 | case RXRPC_SECURITY_RXKAD: | ||
627 | size += 2 * 4; /* length, security index (switch ID) */ | ||
628 | size += 8 * 4; /* viceid, kvno, key*2, begin, end, | ||
629 | * primary, tktlen */ | ||
630 | size += (token->kad->ticket_len + 3) & ~3; /* ticket */ | ||
631 | ntoks++; | ||
632 | break; | ||
633 | |||
634 | default: /* can't encode */ | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | if (!buffer || buflen < size) | ||
640 | return size; | ||
641 | |||
642 | xdr = (__be32 __user *) buffer; | ||
643 | zero = 0; | ||
644 | #define ENCODE(x) \ | ||
645 | do { \ | ||
646 | __be32 y = htonl(x); \ | ||
647 | if (put_user(y, xdr++) < 0) \ | ||
648 | goto fault; \ | ||
649 | } while(0) | ||
650 | |||
651 | ENCODE(0); /* flags */ | ||
652 | ENCODE(cnlen); /* cellname length */ | ||
653 | if (copy_to_user(xdr, key->description + 4, cnlen) != 0) | ||
654 | goto fault; | ||
655 | if (cnlen & 3 && | ||
656 | copy_to_user((u8 *)xdr + cnlen, &zero, 4 - (cnlen & 3)) != 0) | ||
657 | goto fault; | ||
658 | xdr += (cnlen + 3) >> 2; | ||
659 | ENCODE(ntoks); /* token count */ | ||
660 | |||
661 | for (token = key->payload.data; token; token = token->next) { | ||
662 | toksize = 1 * 4; /* sec index */ | ||
663 | |||
664 | switch (token->security_index) { | ||
665 | case RXRPC_SECURITY_RXKAD: | ||
666 | toksize += 8 * 4; | ||
667 | toksize += (token->kad->ticket_len + 3) & ~3; | ||
668 | ENCODE(toksize); | ||
669 | ENCODE(token->security_index); | ||
670 | ENCODE(token->kad->vice_id); | ||
671 | ENCODE(token->kad->kvno); | ||
672 | if (copy_to_user(xdr, token->kad->session_key, 8) != 0) | ||
673 | goto fault; | ||
674 | xdr += 8 >> 2; | ||
675 | ENCODE(token->kad->start); | ||
676 | ENCODE(token->kad->expiry); | ||
677 | ENCODE(token->kad->primary_flag); | ||
678 | tktlen = token->kad->ticket_len; | ||
679 | ENCODE(tktlen); | ||
680 | if (copy_to_user(xdr, token->kad->ticket, tktlen) != 0) | ||
681 | goto fault; | ||
682 | if (tktlen & 3 && | ||
683 | copy_to_user((u8 *)xdr + tktlen, &zero, | ||
684 | 4 - (tktlen & 3)) != 0) | ||
685 | goto fault; | ||
686 | xdr += (tktlen + 3) >> 2; | ||
687 | break; | ||
688 | |||
689 | default: | ||
690 | break; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | #undef ENCODE | ||
695 | |||
696 | ASSERTCMP((char __user *) xdr - buffer, ==, size); | ||
697 | _leave(" = %zu", size); | ||
698 | return size; | ||
699 | |||
700 | fault: | ||
701 | _leave(" = -EFAULT"); | ||
702 | return -EFAULT; | ||
703 | } | ||