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>
This commit is contained in:
parent
5df36e78da
commit
f0768ebd09
153
fs/nfs/super.c
153
fs/nfs/super.c
@ -813,6 +813,89 @@ static void nfs4_fill_super(struct super_block *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
|
||||
*/
|
||||
@ -826,68 +909,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
|
||||
rpc_authflavor_t authflavour;
|
||||
struct nfs_fh mntfh;
|
||||
struct dentry *mntroot;
|
||||
char *p, *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
|
||||
char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
|
||||
int error;
|
||||
|
||||
if (data == NULL) {
|
||||
dprintk("%s: missing data argument\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/* Validate the mount data */
|
||||
error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
|
||||
&hostname, &mntpath, &ip_addr);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
|
||||
/* Get a volume representation */
|
||||
server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
|
||||
@ -932,10 +961,6 @@ out:
|
||||
kfree(hostname);
|
||||
return error;
|
||||
|
||||
out_err:
|
||||
error = PTR_ERR(p);
|
||||
goto out;
|
||||
|
||||
out_free:
|
||||
nfs_free_server(server);
|
||||
goto out;
|
||||
|
Loading…
x
Reference in New Issue
Block a user