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:
committed by
Trond Myklebust
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);
|
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,
|
|||||||
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) {
|
goto out;
|
||||||
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;
|
|
||||||
|
|
||||||
/* 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 @@ out:
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user