diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-27 16:15:00 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-09-28 13:43:34 -0400 |
commit | 0cac120233305b614cfe3ad419f3655876066017 (patch) | |
tree | 131f7c1d4dc97124397bdb86759842fe22052227 /fs/nfs/idmap.c | |
parent | e9ab41b620e4b679ed069ab05cb85e67870b7c87 (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.c | 62 |
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 @@ | |||
55 | static const struct cred *id_resolver_cache; | 55 | static const struct cred *id_resolver_cache; |
56 | static struct key_type key_type_id_resolver_legacy; | 56 | static struct key_type key_type_id_resolver_legacy; |
57 | 57 | ||
58 | struct idmap { | ||
59 | struct rpc_pipe *idmap_pipe; | ||
60 | struct key_construction *idmap_key_cons; | ||
61 | struct mutex idmap_mutex; | ||
62 | }; | ||
63 | |||
64 | struct idmap_legacy_upcalldata { | 58 | struct 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 | ||
65 | struct 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 | ||
664 | static bool | 665 | static bool |
665 | nfs_idmap_prepare_pipe_upcall(struct idmap *idmap, | 666 | nfs_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 | ||
676 | static void | 677 | static void |
677 | nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret) | 678 | nfs_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 | ||
685 | static void | 687 | static void |
686 | nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret) | 688 | nfs_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; |
727 | out2: | 727 | out2: |
@@ -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 | ||
741 | static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey) | 741 | static 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 | 766 | out: | |
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 | ||
824 | static void | 836 | static void |