aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/idmap.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-09-27 16:15:00 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-09-28 13:43:34 -0400
commit0cac120233305b614cfe3ad419f3655876066017 (patch)
tree131f7c1d4dc97124397bdb86759842fe22052227 /fs/nfs/idmap.c
parente9ab41b620e4b679ed069ab05cb85e67870b7c87 (diff)
NFSv4: Ensure that idmap_pipe_downcall sanity-checks the downcall data
Use the idmapper upcall data to verify that the legacy idmapper daemon is indeed responding to an upcall that we sent. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Bryan Schumaker <bjschuma@netapp.com>
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r--fs/nfs/idmap.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 8222ad861456..7ac93e0dd4cf 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -55,18 +55,19 @@
55static const struct cred *id_resolver_cache; 55static const struct cred *id_resolver_cache;
56static struct key_type key_type_id_resolver_legacy; 56static struct key_type key_type_id_resolver_legacy;
57 57
58struct idmap {
59 struct rpc_pipe *idmap_pipe;
60 struct key_construction *idmap_key_cons;
61 struct mutex idmap_mutex;
62};
63
64struct idmap_legacy_upcalldata { 58struct idmap_legacy_upcalldata {
65 struct rpc_pipe_msg pipe_msg; 59 struct rpc_pipe_msg pipe_msg;
66 struct idmap_msg idmap_msg; 60 struct idmap_msg idmap_msg;
61 struct key_construction *key_cons;
67 struct idmap *idmap; 62 struct idmap *idmap;
68}; 63};
69 64
65struct idmap {
66 struct rpc_pipe *idmap_pipe;
67 struct idmap_legacy_upcalldata *idmap_upcall_data;
68 struct mutex idmap_mutex;
69};
70
70/** 71/**
71 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields 72 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
72 * @fattr: fully initialised struct nfs_fattr 73 * @fattr: fully initialised struct nfs_fattr
@@ -663,29 +664,30 @@ out:
663 664
664static bool 665static bool
665nfs_idmap_prepare_pipe_upcall(struct idmap *idmap, 666nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
666 struct key_construction *cons) 667 struct idmap_legacy_upcalldata *data)
667{ 668{
668 if (idmap->idmap_key_cons != NULL) { 669 if (idmap->idmap_upcall_data != NULL) {
669 WARN_ON_ONCE(1); 670 WARN_ON_ONCE(1);
670 return false; 671 return false;
671 } 672 }
672 idmap->idmap_key_cons = cons; 673 idmap->idmap_upcall_data = data;
673 return true; 674 return true;
674} 675}
675 676
676static void 677static void
677nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret) 678nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
678{ 679{
679 struct key_construction *cons = idmap->idmap_key_cons; 680 struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
680 681
681 idmap->idmap_key_cons = NULL; 682 kfree(idmap->idmap_upcall_data);
683 idmap->idmap_upcall_data = NULL;
682 complete_request_key(cons, ret); 684 complete_request_key(cons, ret);
683} 685}
684 686
685static void 687static void
686nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret) 688nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
687{ 689{
688 if (idmap->idmap_key_cons != NULL) 690 if (idmap->idmap_upcall_data != NULL)
689 nfs_idmap_complete_pipe_upcall_locked(idmap, ret); 691 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
690} 692}
691 693
@@ -714,14 +716,12 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
714 goto out2; 716 goto out2;
715 717
716 ret = -EAGAIN; 718 ret = -EAGAIN;
717 if (!nfs_idmap_prepare_pipe_upcall(idmap, cons)) 719 if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
718 goto out2; 720 goto out2;
719 721
720 ret = rpc_queue_upcall(idmap->idmap_pipe, msg); 722 ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
721 if (ret < 0) { 723 if (ret < 0)
722 nfs_idmap_abort_pipe_upcall(idmap, ret); 724 nfs_idmap_abort_pipe_upcall(idmap, ret);
723 kfree(data);
724 }
725 725
726 return ret; 726 return ret;
727out2: 727out2:
@@ -738,21 +738,32 @@ static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *dat
738 authkey); 738 authkey);
739} 739}
740 740
741static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey) 741static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
742 struct idmap_msg *upcall,
743 struct key *key, struct key *authkey)
742{ 744{
743 char id_str[NFS_UINT_MAXLEN]; 745 char id_str[NFS_UINT_MAXLEN];
744 int ret = -EINVAL; 746 int ret = -ENOKEY;
745 747
748 /* ret = -ENOKEY */
749 if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
750 goto out;
746 switch (im->im_conv) { 751 switch (im->im_conv) {
747 case IDMAP_CONV_NAMETOID: 752 case IDMAP_CONV_NAMETOID:
753 if (strcmp(upcall->im_name, im->im_name) != 0)
754 break;
748 sprintf(id_str, "%d", im->im_id); 755 sprintf(id_str, "%d", im->im_id);
749 ret = nfs_idmap_instantiate(key, authkey, id_str); 756 ret = nfs_idmap_instantiate(key, authkey, id_str);
750 break; 757 break;
751 case IDMAP_CONV_IDTONAME: 758 case IDMAP_CONV_IDTONAME:
759 if (upcall->im_id != im->im_id)
760 break;
752 ret = nfs_idmap_instantiate(key, authkey, im->im_name); 761 ret = nfs_idmap_instantiate(key, authkey, im->im_name);
753 break; 762 break;
763 default:
764 ret = -EINVAL;
754 } 765 }
755 766out:
756 return ret; 767 return ret;
757} 768}
758 769
@@ -770,10 +781,11 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
770 * will have been woken up and someone else may now have used 781 * will have been woken up and someone else may now have used
771 * idmap_key_cons - so after this point we may no longer touch it. 782 * idmap_key_cons - so after this point we may no longer touch it.
772 */ 783 */
773 cons = idmap->idmap_key_cons; 784 if (idmap->idmap_upcall_data == NULL)
774 if (cons == NULL)
775 goto out_noupcall; 785 goto out_noupcall;
776 786
787 cons = idmap->idmap_upcall_data->key_cons;
788
777 if (mlen != sizeof(im)) { 789 if (mlen != sizeof(im)) {
778 ret = -ENOSPC; 790 ret = -ENOSPC;
779 goto out; 791 goto out;
@@ -793,9 +805,11 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
793 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) { 805 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
794 ret = -EINVAL; 806 ret = -EINVAL;
795 goto out; 807 goto out;
796 } 808}
797 809
798 ret = nfs_idmap_read_message(&im, cons->key, cons->authkey); 810 ret = nfs_idmap_read_and_verify_message(&im,
811 &idmap->idmap_upcall_data->idmap_msg,
812 cons->key, cons->authkey);
799 if (ret >= 0) { 813 if (ret >= 0) {
800 key_set_timeout(cons->key, nfs_idmap_cache_timeout); 814 key_set_timeout(cons->key, nfs_idmap_cache_timeout);
801 ret = mlen; 815 ret = mlen;
@@ -817,8 +831,6 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
817 831
818 if (msg->errno) 832 if (msg->errno)
819 nfs_idmap_abort_pipe_upcall(idmap, msg->errno); 833 nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
820 /* Free memory allocated in nfs_idmap_legacy_upcall() */
821 kfree(data);
822} 834}
823 835
824static void 836static void