aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-09-13 21:17:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-15 05:44:28 -0400
commited6dd18b5aceb322da9840f01a68d648e91c8a72 (patch)
tree0ba7267df89a1d630b8ac6aa326b43572c785bc1
parent339412841d7620f93fea805fbd7469f08186f458 (diff)
RxRPC: Allow RxRPC keys to be read
Allow RxRPC keys to be read. This is to allow pioctl() to be implemented in userspace. RxRPC keys are read out in XDR format. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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 a3a7acb5071..bf4d623ee1c 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}