[PATCH 09/13] NFS: Implement NFSv2/3 in-kernel mount option parsing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---

 fs/nfs/super.c |  130 +++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a9f698b..7b7cacb 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -935,8 +935,6 @@ static struct nfs_mount_data *nfs_convert_mount_opts(const char *options)
 	if (args == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	args->nmd.version = 7;
-
 	args->nmd.flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP);
 	args->nmd.rsize = NFS_MAX_FILE_IO_SIZE;
 	args->nmd.wsize = NFS_MAX_FILE_IO_SIZE;
@@ -989,71 +987,74 @@ out_invalid:
  * Validate the NFS2/NFS3 mount data
  * - fills in the mount root filehandle
  */
-static int nfs_validate_mount_data(struct nfs_mount_data *data,
-				   struct nfs_fh *mntfh)
+static int nfs_validate_mount_data(struct nfs_mount_data **options,
+				   struct nfs_fh *mntfh,
+				   const char *dev_name)
 {
-	if (data == NULL) {
-		dprintk("%s: missing data argument\n", __FUNCTION__);
-		return -EINVAL;
-	}
+	struct nfs_mount_data *data = *options;
+	unsigned int len;
+	char *c;
+	int status;
 
-	if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
-		dprintk("%s: bad mount version\n", __FUNCTION__);
-		return -EINVAL;
-	}
+	if (data == NULL)
+		goto out_no_data;
 
 	switch (data->version) {
-		case 1:
-			data->namlen = 0;
-		case 2:
-			data->bsize  = 0;
-		case 3:
-			if (data->flags & NFS_MOUNT_VER3) {
-				dprintk("%s: mount structure version %d does not support NFSv3\n",
-						__FUNCTION__,
-						data->version);
-				return -EINVAL;
-			}
-			data->root.size = NFS2_FHSIZE;
-			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
-		case 4:
-			if (data->flags & NFS_MOUNT_SECFLAVOUR) {
-				dprintk("%s: mount structure version %d does not support strong security\n",
-						__FUNCTION__,
-						data->version);
-				return -EINVAL;
-			}
-		case 5:
-			memset(data->context, 0, sizeof(data->context));
+	case 1:
+		data->namlen = 0;
+	case 2:
+		data->bsize  = 0;
+	case 3:
+		if (data->flags & NFS_MOUNT_VER3)
+			goto out_no_v3;
+		data->root.size = NFS2_FHSIZE;
+		memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+	case 4:
+		if (data->flags & NFS_MOUNT_SECFLAVOUR)
+			goto out_no_sec;
+	case 5:
+		memset(data->context, 0, sizeof(data->context));
+	case 6:
+		break;
+	default:
+		data = nfs_convert_mount_opts((char *) data);
+		if (IS_ERR(data))
+			return PTR_ERR(data);
+		*options = data;
+
+		c = strchr(dev_name, ':');
+		if (c == NULL)
+			return -EINVAL;
+		len = c - dev_name - 1;
+		if (len > 256)
+			return -EINVAL;
+		strncpy(data->hostname, dev_name, len);
+
+		status = nfs_try_mount(data, ++c);
+		if (status)
+			return -EINVAL;
 	}
 
-	/* Set the pseudoflavor */
 	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
 		data->pseudoflavor = RPC_AUTH_UNIX;
 
 #ifndef CONFIG_NFS_V3
-	/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
-	if (data->flags & NFS_MOUNT_VER3) {
-		dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
-		return -EPROTONOSUPPORT;
-	}
-#endif /* CONFIG_NFS_V3 */
+	if (data->flags & NFS_MOUNT_VER3)
+		goto out_v3_not_compiled;
+#endif /* !CONFIG_NFS_V3 */
 
 	/* We now require that the mount process passes the remote address */
 	if (!nfs_verify_server_address((struct sockaddr *) &data->addr,
 						sizeof(data->addr)))
  		return -EINVAL;
 
-	/* Prepare the root filehandle */
 	if (data->flags & NFS_MOUNT_VER3)
 		mntfh->size = data->root.size;
 	else
 		mntfh->size = NFS2_FHSIZE;
 
-	if (mntfh->size > sizeof(mntfh->data)) {
-		dprintk("%s: invalid root filehandle\n", __FUNCTION__);
-		return -EINVAL;
-	}
+	if (mntfh->size > sizeof(mntfh->data))
+		goto out_invalid_fh;
 
 	memcpy(mntfh->data, data->root.data, mntfh->size);
 	if (mntfh->size < sizeof(mntfh->data))
@@ -1061,6 +1062,30 @@ static int nfs_validate_mount_data(struct nfs_mount_data *data,
 		       sizeof(mntfh->data) - mntfh->size);
 
 	return 0;
+
+out_no_data:
+	dprintk("NFS: mount program didn't pass any mount data\n");
+	return -EINVAL;
+
+out_no_v3:
+	dprintk("NFS: nfs_mount_data version %d does not support NFSv3\n",
+		data->version);
+	return -EINVAL;
+
+out_no_sec:
+	dprintk("NFS: nfs_mount_data version %d supports only AUTH_SYS\n",
+		data->version);
+	return -EINVAL;
+
+#ifndef CONFIG_NFS_V3
+out_v3_not_compiled:
+	dprintk("NFS: NFSv3 is not compiled into kernel\n");
+	return -EPROTONOSUPPORT;
+#endif /* !CONFIG_NFS_V3 */
+
+out_invalid_fh:
+	dprintk("NFS: invalid root filehandle\n");
+	return -EINVAL;
 }
 
 /*
@@ -1168,9 +1193,12 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 	int error;
 
 	/* Validate the mount data */
-	error = nfs_validate_mount_data(data, &mntfh);
-	if (error < 0)
+	error = nfs_validate_mount_data(&data, &mntfh, dev_name);
+	if (error < 0) {
+		if (data != raw_data)
+			kfree(data);
 		return error;
+	}
 
 	/* Get a volume representation */
 	server = nfs_create_server(data, &mntfh);
@@ -1206,16 +1234,22 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 	s->s_flags |= MS_ACTIVE;
 	mnt->mnt_sb = s;
 	mnt->mnt_root = mntroot;
+	if (data != raw_data)
+		kfree(data);
 	return 0;
 
 out_err_nosb:
 	nfs_free_server(server);
 out_err_noserver:
+	if (data != raw_data)
+		kfree(data);
 	return error;
 
 error_splat_super:
 	up_write(&s->s_umount);
 	deactivate_super(s);
+	if (data != raw_data)
+		kfree(data);
 	return error;
 }
 

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux