diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-07-01 12:13:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:45 -0400 |
commit | f0768ebd09385551277fcbc8b28c29eb491bf9e2 (patch) | |
tree | c89bec443ac7bc8967eb24f8de71e7fb8498fc3e /fs/nfs/super.c | |
parent | 5df36e78da9db1c5f02b429116ed98902bcc75e5 (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>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 153 |
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 | */ | ||
819 | static 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 | |||
880 | out_no_data: | ||
881 | dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n"); | ||
882 | return -EINVAL; | ||
883 | |||
884 | out_inval_auth: | ||
885 | dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n", | ||
886 | data->auth_flavourlen); | ||
887 | return -EINVAL; | ||
888 | |||
889 | out_no_address: | ||
890 | dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n"); | ||
891 | return -EINVAL; | ||
892 | |||
893 | out_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 | */ |
819 | static int nfs4_get_sb(struct file_system_type *fs_type, | 902 | static 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 | ||
935 | out_err: | ||
936 | error = PTR_ERR(p); | ||
937 | goto out; | ||
938 | |||
939 | out_free: | 964 | out_free: |
940 | nfs_free_server(server); | 965 | nfs_free_server(server); |
941 | goto out; | 966 | goto out; |