Commit 8e02f6b9 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

NFS: Update MNT and MNT3 reply decoding functions



Solder xdr_stream-based XDR decoding functions into the in-kernel mountd
client that are more careful about checking data types and watching for
buffer overflows.  The new MNT3 decoder includes support for auth-flavor
list decoding.

The "_sz" macro for MNT3 replies was missing the size of the file handle.
I've added this back, and included the size of the auth flavor array.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent a14017db
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -83,6 +83,8 @@ struct nfs_mount_request {
	unsigned short		protocol;
	unsigned short		protocol;
	struct nfs_fh		*fh;
	struct nfs_fh		*fh;
	int			noresvport;
	int			noresvport;
	unsigned int		*auth_flav_len;
	rpc_authflavor_t	*auth_flavs;
};
};


extern int nfs_mount(struct nfs_mount_request *info);
extern int nfs_mount(struct nfs_mount_request *info);
+49 −14
Original line number Original line Diff line number Diff line
@@ -39,6 +39,9 @@
 * XDR argument and result sizes
 * XDR argument and result sizes
 */
 */
#define MNT_enc_dirpath_sz	encode_dirpath_sz
#define MNT_enc_dirpath_sz	encode_dirpath_sz
#define MNT_dec_mountres_sz	(MNT_status_sz + MNT_fhandle_sz)
#define MNT_dec_mountres3_sz	(MNT_status_sz + MNT_fhandle_sz + \
				 MNT_authflav3_sz)


/*
/*
 * Defined by RFC 1094, section A.5
 * Defined by RFC 1094, section A.5
@@ -140,8 +143,10 @@ struct mnt_fhstatus {
 */
 */
int nfs_mount(struct nfs_mount_request *info)
int nfs_mount(struct nfs_mount_request *info)
{
{
	struct mnt_fhstatus	result = {
	struct mountres	result = {
		.fh		= info->fh
		.fh		= info->fh,
		.auth_count	= info->auth_flav_len,
		.auth_flavors	= info->auth_flavs,
	};
	};
	struct rpc_message msg	= {
	struct rpc_message msg	= {
		.rpc_argp	= info->dirpath,
		.rpc_argp	= info->dirpath,
@@ -180,7 +185,7 @@ int nfs_mount(struct nfs_mount_request *info)


	if (status < 0)
	if (status < 0)
		goto out_call_err;
		goto out_call_err;
	if (result.status != 0)
	if (result.errno != 0)
		goto out_mnt_err;
		goto out_mnt_err;


	dprintk("NFS: MNT request succeeded\n");
	dprintk("NFS: MNT request succeeded\n");
@@ -191,16 +196,16 @@ out:


out_clnt_err:
out_clnt_err:
	status = PTR_ERR(mnt_clnt);
	status = PTR_ERR(mnt_clnt);
	dprintk("NFS: failed to create RPC client, status=%d\n", status);
	dprintk("NFS: failed to create MNT RPC client, status=%d\n", status);
	goto out;
	goto out;


out_call_err:
out_call_err:
	dprintk("NFS: failed to start MNT request, status=%d\n", status);
	dprintk("NFS: MNT request failed, status=%d\n", status);
	goto out;
	goto out;


out_mnt_err:
out_mnt_err:
	dprintk("NFS: MNT server returned result %d\n", result.status);
	dprintk("NFS: MNT server returned result %d\n", result.errno);
	status = nfs_stat_to_errno(result.status);
	status = result.errno;
	goto out;
	goto out;
}
}


@@ -291,6 +296,20 @@ static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res)
	return 0;
	return 0;
}
}


static int mnt_dec_mountres(struct rpc_rqst *req, __be32 *p,
			    struct mountres *res)
{
	struct xdr_stream xdr;
	int status;

	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);

	status = decode_status(&xdr, res);
	if (unlikely(status != 0 || res->errno != 0))
		return status;
	return decode_fhandle(&xdr, res);
}

static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
{
{
	unsigned int i;
	unsigned int i;
@@ -371,6 +390,25 @@ static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
	return 0;
	return 0;
}
}


static int mnt_dec_mountres3(struct rpc_rqst *req, __be32 *p,
			     struct mountres *res)
{
	struct xdr_stream xdr;
	int status;

	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);

	status = decode_fhs_status(&xdr, res);
	if (unlikely(status != 0 || res->errno != 0))
		return status;
	status = decode_fhandle3(&xdr, res);
	if (unlikely(status != 0)) {
		res->errno = -EBADHANDLE;
		return 0;
	}
	return decode_auth_flavors(&xdr, res);
}

static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
				struct mnt_fhstatus *res)
				struct mnt_fhstatus *res)
{
{
@@ -388,16 +426,13 @@ static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
	return 0;
	return 0;
}
}


#define MNT_fhstatus_sz		(1 + 8)
#define MNT_fhstatus3_sz	(1 + 16)

static struct rpc_procinfo mnt_procedures[] = {
static struct rpc_procinfo mnt_procedures[] = {
	[MOUNTPROC_MNT] = {
	[MOUNTPROC_MNT] = {
		.p_proc		= MOUNTPROC_MNT,
		.p_proc		= MOUNTPROC_MNT,
		.p_encode	= (kxdrproc_t)mnt_enc_dirpath,
		.p_encode	= (kxdrproc_t)mnt_enc_dirpath,
		.p_decode	= (kxdrproc_t) xdr_decode_fhstatus,
		.p_decode	= (kxdrproc_t)mnt_dec_mountres,
		.p_arglen	= MNT_enc_dirpath_sz,
		.p_arglen	= MNT_enc_dirpath_sz,
		.p_replen	= MNT_fhstatus_sz,
		.p_replen	= MNT_dec_mountres_sz,
		.p_statidx	= MOUNTPROC_MNT,
		.p_statidx	= MOUNTPROC_MNT,
		.p_name		= "MOUNT",
		.p_name		= "MOUNT",
	},
	},
@@ -407,9 +442,9 @@ static struct rpc_procinfo mnt3_procedures[] = {
	[MOUNTPROC3_MNT] = {
	[MOUNTPROC3_MNT] = {
		.p_proc		= MOUNTPROC3_MNT,
		.p_proc		= MOUNTPROC3_MNT,
		.p_encode	= (kxdrproc_t)mnt_enc_dirpath,
		.p_encode	= (kxdrproc_t)mnt_enc_dirpath,
		.p_decode	= (kxdrproc_t) xdr_decode_fhstatus3,
		.p_decode	= (kxdrproc_t)mnt_dec_mountres3,
		.p_arglen	= MNT_enc_dirpath_sz,
		.p_arglen	= MNT_enc_dirpath_sz,
		.p_replen	= MNT_fhstatus3_sz,
		.p_replen	= MNT_dec_mountres3_sz,
		.p_statidx	= MOUNTPROC3_MNT,
		.p_statidx	= MOUNTPROC3_MNT,
		.p_name		= "MOUNT",
		.p_name		= "MOUNT",
	},
	},
+2 −0
Original line number Original line Diff line number Diff line
@@ -490,6 +490,7 @@ static int __init root_nfs_get_handle(void)
{
{
	struct nfs_fh fh;
	struct nfs_fh fh;
	struct sockaddr_in sin;
	struct sockaddr_in sin;
	unsigned int auth_flav_len = 0;
	struct nfs_mount_request request = {
	struct nfs_mount_request request = {
		.sap		= (struct sockaddr *)&sin,
		.sap		= (struct sockaddr *)&sin,
		.salen		= sizeof(sin),
		.salen		= sizeof(sin),
@@ -499,6 +500,7 @@ static int __init root_nfs_get_handle(void)
		.protocol	= (nfs_data.flags & NFS_MOUNT_TCP) ?
		.protocol	= (nfs_data.flags & NFS_MOUNT_TCP) ?
					XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
					XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
		.fh		= &fh,
		.fh		= &fh,
		.auth_flav_len	= &auth_flav_len,
	};
	};
	int status;
	int status;


+2 −0
Original line number Original line Diff line number Diff line
@@ -1380,6 +1380,7 @@ out_security_failure:
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
			 struct nfs_fh *root_fh)
			 struct nfs_fh *root_fh)
{
{
	unsigned int auth_flavor_len = 0;
	struct nfs_mount_request request = {
	struct nfs_mount_request request = {
		.sap		= (struct sockaddr *)
		.sap		= (struct sockaddr *)
						&args->mount_server.address,
						&args->mount_server.address,
@@ -1387,6 +1388,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
		.protocol	= args->mount_server.protocol,
		.protocol	= args->mount_server.protocol,
		.fh		= root_fh,
		.fh		= root_fh,
		.noresvport	= args->flags & NFS_MOUNT_NORESVPORT,
		.noresvport	= args->flags & NFS_MOUNT_NORESVPORT,
		.auth_flav_len	= &auth_flavor_len,
	};
	};
	int status;
	int status;