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 | |
| 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>
| -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; |
