Commit f0768ebd authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 5df36e78
...@@ -813,6 +813,89 @@ static void nfs4_fill_super(struct super_block *sb) ...@@ -813,6 +813,89 @@ static void nfs4_fill_super(struct super_block *sb)
nfs_initialise_sb(sb); nfs_initialise_sb(sb);
} }
/*
* Validate NFSv4 mount options
*/
static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
const char *dev_name,
struct sockaddr_in *addr,
rpc_authflavor_t *authflavour,
char **hostname,
char **mntpath,
char **ip_addr)
{
struct nfs4_mount_data *data = *options;
char *c;
if (data == NULL)
goto out_no_data;
switch (data->version) {
case 1:
if (data->host_addrlen != sizeof(*addr))
goto out_no_address;
if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
return -EFAULT;
if (addr->sin_port == 0)
addr->sin_port = htons(NFS_PORT);
if (!nfs_verify_server_address((struct sockaddr *) addr))
goto out_no_address;
switch (data->auth_flavourlen) {
case 0:
*authflavour = RPC_AUTH_UNIX;
break;
case 1:
if (copy_from_user(authflavour, data->auth_flavours,
sizeof(*authflavour)))
return -EFAULT;
break;
default:
goto out_inval_auth;
}
c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
if (IS_ERR(c))
return PTR_ERR(c);
*hostname = c;
c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
if (IS_ERR(c))
return PTR_ERR(c);
*mntpath = c;
dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
c = strndup_user(data->client_addr.data, 16);
if (IS_ERR(c))
return PTR_ERR(c);
*ip_addr = c;
break;
default:
goto out_bad_version;
}
return 0;
out_no_data:
dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
return -EINVAL;
out_inval_auth:
dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
data->auth_flavourlen);
return -EINVAL;
out_no_address:
dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
return -EINVAL;
out_bad_version:
dfprintk(MOUNT, "NFS4: bad nfs_mount_data version %d\n",
data->version);
return -EINVAL;
}
/* /*
* Get the superblock for an NFS4 mountpoint * Get the superblock for an NFS4 mountpoint
*/ */
...@@ -826,68 +909,14 @@ 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,
rpc_authflavor_t authflavour; rpc_authflavor_t authflavour;
struct nfs_fh mntfh; struct nfs_fh mntfh;
struct dentry *mntroot; struct dentry *mntroot;
char *p, *mntpath = NULL, *hostname = NULL, *ip_addr = NULL; char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
int error; int error;
if (data == NULL) { /* Validate the mount data */
dprintk("%s: missing data argument\n", __FUNCTION__); error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
return -EINVAL; &hostname, &mntpath, &ip_addr);
} if (error < 0)
if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
dprintk("%s: bad mount version\n", __FUNCTION__);
return -EINVAL;
}
/* We now require that the mount process passes the remote address */
if (data->host_addrlen != sizeof(addr))
return -EINVAL;
if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
return -EFAULT;
if (!nfs_verify_server_address((struct sockaddr *) &addr)) {
dprintk("%s: mount program didn't pass remote IP address!\n",
__FUNCTION__);
return -EINVAL;
}
/* RFC3530: The default port for NFS is 2049 */
if (addr.sin_port == 0)
addr.sin_port = htons(NFS_PORT);
/* Grab the authentication type */
authflavour = RPC_AUTH_UNIX;
if (data->auth_flavourlen != 0) {
if (data->auth_flavourlen != 1) {
dprintk("%s: Invalid number of RPC auth flavours %d.\n",
__FUNCTION__, data->auth_flavourlen);
error = -EINVAL;
goto out;
}
if (copy_from_user(&authflavour, data->auth_flavours,
sizeof(authflavour))) {
error = -EFAULT;
goto out; goto out;
}
}
p = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
if (IS_ERR(p))
goto out_err;
hostname = p;
p = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
if (IS_ERR(p))
goto out_err;
mntpath = p;
dprintk("MNTPATH: %s\n", mntpath);
p = strndup_user(data->client_addr.data, 16);
if (IS_ERR(p))
goto out_err;
ip_addr = p;
/* Get a volume representation */ /* Get a volume representation */
server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
...@@ -932,10 +961,6 @@ static int nfs4_get_sb(struct file_system_type *fs_type, ...@@ -932,10 +961,6 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
kfree(hostname); kfree(hostname);
return error; return error;
out_err:
error = PTR_ERR(p);
goto out;
out_free: out_free:
nfs_free_server(server); nfs_free_server(server);
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment