aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-07-01 12:13:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:45 -0400
commitf0768ebd09385551277fcbc8b28c29eb491bf9e2 (patch)
treec89bec443ac7bc8967eb24f8de71e7fb8498fc3e
parent5df36e78da9db1c5f02b429116ed98902bcc75e5 (diff)
NFS: Introduce nfs4_validate_mount_options
Refactor NFSv4 mount processing to break out mount data validation in the same way it's broken out in the NFSv2/v3 mount path. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/super.c153
1 files changed, 89 insertions, 64 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index baf75e9bd3fe..ed3ec4477a0f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -814,6 +814,89 @@ static void nfs4_fill_super(struct super_block *sb)
814} 814}
815 815
816/* 816/*
817 * Validate NFSv4 mount options
818 */
819static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
820 const char *dev_name,
821 struct sockaddr_in *addr,
822 rpc_authflavor_t *authflavour,
823 char **hostname,
824 char **mntpath,
825 char **ip_addr)
826{
827 struct nfs4_mount_data *data = *options;
828 char *c;
829
830 if (data == NULL)
831 goto out_no_data;
832
833 switch (data->version) {
834 case 1:
835 if (data->host_addrlen != sizeof(*addr))
836 goto out_no_address;
837 if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
838 return -EFAULT;
839 if (addr->sin_port == 0)
840 addr->sin_port = htons(NFS_PORT);
841 if (!nfs_verify_server_address((struct sockaddr *) addr))
842 goto out_no_address;
843
844 switch (data->auth_flavourlen) {
845 case 0:
846 *authflavour = RPC_AUTH_UNIX;
847 break;
848 case 1:
849 if (copy_from_user(authflavour, data->auth_flavours,
850 sizeof(*authflavour)))
851 return -EFAULT;
852 break;
853 default:
854 goto out_inval_auth;
855 }
856
857 c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
858 if (IS_ERR(c))
859 return PTR_ERR(c);
860 *hostname = c;
861
862 c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
863 if (IS_ERR(c))
864 return PTR_ERR(c);
865 *mntpath = c;
866 dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
867
868 c = strndup_user(data->client_addr.data, 16);
869 if (IS_ERR(c))
870 return PTR_ERR(c);
871 *ip_addr = c;
872
873 break;
874 default:
875 goto out_bad_version;
876 }
877
878 return 0;
879
880out_no_data:
881 dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
882 return -EINVAL;
883
884out_inval_auth:
885 dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
886 data->auth_flavourlen);
887 return -EINVAL;
888
889out_no_address:
890 dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
891 return -EINVAL;
892
893out_bad_version:
894 dfprintk(MOUNT, "NFS4: bad nfs_mount_data version %d\n",
895 data->version);
896 return -EINVAL;
897}
898
899/*
817 * Get the superblock for an NFS4 mountpoint 900 * Get the superblock for an NFS4 mountpoint
818 */ 901 */
819static int nfs4_get_sb(struct file_system_type *fs_type, 902static int nfs4_get_sb(struct file_system_type *fs_type,
@@ -826,68 +909,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
826 rpc_authflavor_t authflavour; 909 rpc_authflavor_t authflavour;
827 struct nfs_fh mntfh; 910 struct nfs_fh mntfh;
828 struct dentry *mntroot; 911 struct dentry *mntroot;
829 char *p, *mntpath = NULL, *hostname = NULL, *ip_addr = NULL; 912 char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
830 int error; 913 int error;
831 914
832 if (data == NULL) { 915 /* Validate the mount data */
833 dprintk("%s: missing data argument\n", __FUNCTION__); 916 error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
834 return -EINVAL; 917 &hostname, &mntpath, &ip_addr);
835 } 918 if (error < 0)
836 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { 919 goto out;
837 dprintk("%s: bad mount version\n", __FUNCTION__);
838 return -EINVAL;
839 }
840
841 /* We now require that the mount process passes the remote address */
842 if (data->host_addrlen != sizeof(addr))
843 return -EINVAL;
844
845 if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
846 return -EFAULT;
847
848 if (!nfs_verify_server_address((struct sockaddr *) &addr)) {
849 dprintk("%s: mount program didn't pass remote IP address!\n",
850 __FUNCTION__);
851 return -EINVAL;
852 }
853
854 /* RFC3530: The default port for NFS is 2049 */
855 if (addr.sin_port == 0)
856 addr.sin_port = htons(NFS_PORT);
857
858 /* Grab the authentication type */
859 authflavour = RPC_AUTH_UNIX;
860 if (data->auth_flavourlen != 0) {
861 if (data->auth_flavourlen != 1) {
862 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
863 __FUNCTION__, data->auth_flavourlen);
864 error = -EINVAL;
865 goto out;
866 }
867
868 if (copy_from_user(&authflavour, data->auth_flavours,
869 sizeof(authflavour))) {
870 error = -EFAULT;
871 goto out;
872 }
873 }
874
875 p = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
876 if (IS_ERR(p))
877 goto out_err;
878 hostname = p;
879
880 p = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
881 if (IS_ERR(p))
882 goto out_err;
883 mntpath = p;
884
885 dprintk("MNTPATH: %s\n", mntpath);
886
887 p = strndup_user(data->client_addr.data, 16);
888 if (IS_ERR(p))
889 goto out_err;
890 ip_addr = p;
891 920
892 /* Get a volume representation */ 921 /* Get a volume representation */
893 server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, 922 server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
@@ -932,10 +961,6 @@ out:
932 kfree(hostname); 961 kfree(hostname);
933 return error; 962 return error;
934 963
935out_err:
936 error = PTR_ERR(p);
937 goto out;
938
939out_free: 964out_free:
940 nfs_free_server(server); 965 nfs_free_server(server);
941 goto out; 966 goto out;