aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc/ar-key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/rxrpc/ar-key.c')
-rw-r--r--net/rxrpc/ar-key.c109
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);
29static void rxrpc_destroy(struct key *); 29static void rxrpc_destroy(struct key *);
30static void rxrpc_destroy_s(struct key *); 30static void rxrpc_destroy_s(struct key *);
31static void rxrpc_describe(const struct key *, struct seq_file *); 31static void rxrpc_describe(const struct key *, struct seq_file *);
32static 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};
44EXPORT_SYMBOL(key_type_rxrpc); 46EXPORT_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}
594EXPORT_SYMBOL(rxrpc_get_null_key); 596EXPORT_SYMBOL(rxrpc_get_null_key);
597
598/*
599 * read the contents of an rxrpc key
600 * - this returns the result in XDR form
601 */
602static 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
700fault:
701 _leave(" = -EFAULT");
702 return -EFAULT;
703}