aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/idmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r--fs/nfs/idmap.c114
1 files changed, 74 insertions, 40 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index a850079467d8..9cc4a3fbf4b0 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
@@ -158,7 +159,7 @@ static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *re
158 return 0; 159 return 0;
159 memcpy(buf, name, namelen); 160 memcpy(buf, name, namelen);
160 buf[namelen] = '\0'; 161 buf[namelen] = '\0';
161 if (strict_strtoul(buf, 0, &val) != 0) 162 if (kstrtoul(buf, 0, &val) != 0)
162 return 0; 163 return 0;
163 *res = val; 164 *res = val;
164 return 1; 165 return 1;
@@ -330,7 +331,6 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
330 ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, 331 ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,
331 name, namelen, type, data, 332 name, namelen, type, data,
332 data_size, idmap); 333 data_size, idmap);
333 idmap->idmap_key_cons = NULL;
334 mutex_unlock(&idmap->idmap_mutex); 334 mutex_unlock(&idmap->idmap_mutex);
335 } 335 }
336 return ret; 336 return ret;
@@ -364,7 +364,7 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ
364 if (data_size <= 0) { 364 if (data_size <= 0) {
365 ret = -EINVAL; 365 ret = -EINVAL;
366 } else { 366 } else {
367 ret = strict_strtol(id_str, 10, &id_long); 367 ret = kstrtol(id_str, 10, &id_long);
368 *id = (__u32)id_long; 368 *id = (__u32)id_long;
369 } 369 }
370 return ret; 370 return ret;
@@ -465,8 +465,6 @@ nfs_idmap_new(struct nfs_client *clp)
465 struct rpc_pipe *pipe; 465 struct rpc_pipe *pipe;
466 int error; 466 int error;
467 467
468 BUG_ON(clp->cl_idmap != NULL);
469
470 idmap = kzalloc(sizeof(*idmap), GFP_KERNEL); 468 idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
471 if (idmap == NULL) 469 if (idmap == NULL)
472 return -ENOMEM; 470 return -ENOMEM;
@@ -510,7 +508,6 @@ static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
510 508
511 switch (event) { 509 switch (event) {
512 case RPC_PIPEFS_MOUNT: 510 case RPC_PIPEFS_MOUNT:
513 BUG_ON(clp->cl_rpcclient->cl_dentry == NULL);
514 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry, 511 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
515 clp->cl_idmap, 512 clp->cl_idmap,
516 clp->cl_idmap->idmap_pipe); 513 clp->cl_idmap->idmap_pipe);
@@ -632,9 +629,6 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
632 substring_t substr; 629 substring_t substr;
633 int token, ret; 630 int token, ret;
634 631
635 memset(im, 0, sizeof(*im));
636 memset(msg, 0, sizeof(*msg));
637
638 im->im_type = IDMAP_TYPE_GROUP; 632 im->im_type = IDMAP_TYPE_GROUP;
639 token = match_token(desc, nfs_idmap_tokens, &substr); 633 token = match_token(desc, nfs_idmap_tokens, &substr);
640 634
@@ -665,6 +659,35 @@ out:
665 return ret; 659 return ret;
666} 660}
667 661
662static bool
663nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
664 struct idmap_legacy_upcalldata *data)
665{
666 if (idmap->idmap_upcall_data != NULL) {
667 WARN_ON_ONCE(1);
668 return false;
669 }
670 idmap->idmap_upcall_data = data;
671 return true;
672}
673
674static void
675nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
676{
677 struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
678
679 kfree(idmap->idmap_upcall_data);
680 idmap->idmap_upcall_data = NULL;
681 complete_request_key(cons, ret);
682}
683
684static void
685nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
686{
687 if (idmap->idmap_upcall_data != NULL)
688 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
689}
690
668static int nfs_idmap_legacy_upcall(struct key_construction *cons, 691static int nfs_idmap_legacy_upcall(struct key_construction *cons,
669 const char *op, 692 const char *op,
670 void *aux) 693 void *aux)
@@ -677,29 +700,28 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
677 int ret = -ENOMEM; 700 int ret = -ENOMEM;
678 701
679 /* msg and im are freed in idmap_pipe_destroy_msg */ 702 /* msg and im are freed in idmap_pipe_destroy_msg */
680 data = kmalloc(sizeof(*data), GFP_KERNEL); 703 data = kzalloc(sizeof(*data), GFP_KERNEL);
681 if (!data) 704 if (!data)
682 goto out1; 705 goto out1;
683 706
684 msg = &data->pipe_msg; 707 msg = &data->pipe_msg;
685 im = &data->idmap_msg; 708 im = &data->idmap_msg;
686 data->idmap = idmap; 709 data->idmap = idmap;
710 data->key_cons = cons;
687 711
688 ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); 712 ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
689 if (ret < 0) 713 if (ret < 0)
690 goto out2; 714 goto out2;
691 715
692 BUG_ON(idmap->idmap_key_cons != NULL); 716 ret = -EAGAIN;
693 idmap->idmap_key_cons = cons; 717 if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
718 goto out2;
694 719
695 ret = rpc_queue_upcall(idmap->idmap_pipe, msg); 720 ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
696 if (ret < 0) 721 if (ret < 0)
697 goto out3; 722 nfs_idmap_abort_pipe_upcall(idmap, ret);
698 723
699 return ret; 724 return ret;
700
701out3:
702 idmap->idmap_key_cons = NULL;
703out2: 725out2:
704 kfree(data); 726 kfree(data);
705out1: 727out1:
@@ -714,21 +736,32 @@ static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *dat
714 authkey); 736 authkey);
715} 737}
716 738
717static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey) 739static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
740 struct idmap_msg *upcall,
741 struct key *key, struct key *authkey)
718{ 742{
719 char id_str[NFS_UINT_MAXLEN]; 743 char id_str[NFS_UINT_MAXLEN];
720 int ret = -EINVAL; 744 int ret = -ENOKEY;
721 745
746 /* ret = -ENOKEY */
747 if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
748 goto out;
722 switch (im->im_conv) { 749 switch (im->im_conv) {
723 case IDMAP_CONV_NAMETOID: 750 case IDMAP_CONV_NAMETOID:
751 if (strcmp(upcall->im_name, im->im_name) != 0)
752 break;
724 sprintf(id_str, "%d", im->im_id); 753 sprintf(id_str, "%d", im->im_id);
725 ret = nfs_idmap_instantiate(key, authkey, id_str); 754 ret = nfs_idmap_instantiate(key, authkey, id_str);
726 break; 755 break;
727 case IDMAP_CONV_IDTONAME: 756 case IDMAP_CONV_IDTONAME:
757 if (upcall->im_id != im->im_id)
758 break;
728 ret = nfs_idmap_instantiate(key, authkey, im->im_name); 759 ret = nfs_idmap_instantiate(key, authkey, im->im_name);
729 break; 760 break;
761 default:
762 ret = -EINVAL;
730 } 763 }
731 764out:
732 return ret; 765 return ret;
733} 766}
734 767
@@ -740,14 +773,16 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
740 struct key_construction *cons; 773 struct key_construction *cons;
741 struct idmap_msg im; 774 struct idmap_msg im;
742 size_t namelen_in; 775 size_t namelen_in;
743 int ret; 776 int ret = -ENOKEY;
744 777
745 /* If instantiation is successful, anyone waiting for key construction 778 /* If instantiation is successful, anyone waiting for key construction
746 * will have been woken up and someone else may now have used 779 * will have been woken up and someone else may now have used
747 * idmap_key_cons - so after this point we may no longer touch it. 780 * idmap_key_cons - so after this point we may no longer touch it.
748 */ 781 */
749 cons = ACCESS_ONCE(idmap->idmap_key_cons); 782 if (idmap->idmap_upcall_data == NULL)
750 idmap->idmap_key_cons = NULL; 783 goto out_noupcall;
784
785 cons = idmap->idmap_upcall_data->key_cons;
751 786
752 if (mlen != sizeof(im)) { 787 if (mlen != sizeof(im)) {
753 ret = -ENOSPC; 788 ret = -ENOSPC;
@@ -768,16 +803,19 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
768 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) { 803 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
769 ret = -EINVAL; 804 ret = -EINVAL;
770 goto out; 805 goto out;
771 } 806}
772 807
773 ret = nfs_idmap_read_message(&im, cons->key, cons->authkey); 808 ret = nfs_idmap_read_and_verify_message(&im,
809 &idmap->idmap_upcall_data->idmap_msg,
810 cons->key, cons->authkey);
774 if (ret >= 0) { 811 if (ret >= 0) {
775 key_set_timeout(cons->key, nfs_idmap_cache_timeout); 812 key_set_timeout(cons->key, nfs_idmap_cache_timeout);
776 ret = mlen; 813 ret = mlen;
777 } 814 }
778 815
779out: 816out:
780 complete_request_key(cons, ret); 817 nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
818out_noupcall:
781 return ret; 819 return ret;
782} 820}
783 821
@@ -788,14 +826,9 @@ idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
788 struct idmap_legacy_upcalldata, 826 struct idmap_legacy_upcalldata,
789 pipe_msg); 827 pipe_msg);
790 struct idmap *idmap = data->idmap; 828 struct idmap *idmap = data->idmap;
791 struct key_construction *cons; 829
792 if (msg->errno) { 830 if (msg->errno)
793 cons = ACCESS_ONCE(idmap->idmap_key_cons); 831 nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
794 idmap->idmap_key_cons = NULL;
795 complete_request_key(cons, msg->errno);
796 }
797 /* Free memory allocated in nfs_idmap_legacy_upcall() */
798 kfree(data);
799} 832}
800 833
801static void 834static void
@@ -803,7 +836,8 @@ idmap_release_pipe(struct inode *inode)
803{ 836{
804 struct rpc_inode *rpci = RPC_I(inode); 837 struct rpc_inode *rpci = RPC_I(inode);
805 struct idmap *idmap = (struct idmap *)rpci->private; 838 struct idmap *idmap = (struct idmap *)rpci->private;
806 idmap->idmap_key_cons = NULL; 839
840 nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
807} 841}
808 842
809int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) 843int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)