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

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
...@@ -83,6 +83,8 @@ struct nfs_mount_request { ...@@ -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);
......
...@@ -39,6 +39,9 @@ ...@@ -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 { ...@@ -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) ...@@ -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 @@ int nfs_mount(struct nfs_mount_request *info) ...@@ -191,16 +196,16 @@ int nfs_mount(struct nfs_mount_request *info)
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) ...@@ -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) ...@@ -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, ...@@ -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[] = { ...@@ -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",
}, },
......
...@@ -490,6 +490,7 @@ static int __init root_nfs_get_handle(void) ...@@ -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) ...@@ -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;
......
...@@ -1380,6 +1380,7 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1380,6 +1380,7 @@ static int nfs_parse_mount_options(char *raw,
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, ...@@ -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;
......
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