Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/nfs4xdr.c | 73 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 4a71346dcd9a..2d2034d7f48e 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -570,24 +570,22 @@ nfsd4_decode_stateid4(struct nfsd4_compoundargs *argp, stateid_t *sid) static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs) { - DECODE_HEAD; struct user_namespace *userns = nfsd_user_namespace(argp->rqstp); - u32 dummy, uid, gid; + u32 dummy, uid, gid, i, nr_secflavs; char *machine_name; - int i; - int nr_secflavs; + __be32 *p; /* callback_sec_params4 */ - READ_BUF(4); - nr_secflavs = be32_to_cpup(p++); + if (xdr_stream_decode_u32(argp->xdr, &nr_secflavs) < 0) + goto xdr_error; if (nr_secflavs) cbs->flavor = (u32)(-1); else /* Is this legal? Be generous, take it to mean AUTH_NONE: */ cbs->flavor = 0; for (i = 0; i < nr_secflavs; ++i) { - READ_BUF(4); - dummy = be32_to_cpup(p++); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; switch (dummy) { case RPC_AUTH_NULL: /* Nothing to read */ @@ -595,24 +593,32 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_ cbs->flavor = RPC_AUTH_NULL; break; case RPC_AUTH_UNIX: - READ_BUF(8); /* stamp */ - dummy = be32_to_cpup(p++); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; /* machine name */ - dummy = be32_to_cpup(p++); - READ_BUF(dummy); - SAVEMEM(machine_name, dummy); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; + p = xdr_inline_decode(argp->xdr, dummy); + if (!p) + goto xdr_error; + machine_name = svcxdr_tmpalloc(argp, dummy); + if (!machine_name) + goto nomem; + memcpy(machine_name, p, dummy); - /* uid, gid */ - READ_BUF(8); + /* uid, gid, gidcount */ + p = xdr_inline_decode(argp->xdr, sizeof(__be32) * 3); + if (!p) + goto xdr_error; uid = be32_to_cpup(p++); gid = be32_to_cpup(p++); - /* more gids */ - READ_BUF(4); - dummy = be32_to_cpup(p++); - READ_BUF(dummy * 4); + dummy = be32_to_cpup(p); + p = xdr_inline_decode(argp->xdr, dummy << 2); + if (!p) + goto xdr_error; if (cbs->flavor == (u32)(-1)) { kuid_t kuid = make_kuid(userns, uid); kgid_t kgid = make_kgid(userns, gid); @@ -629,26 +635,37 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_ case RPC_AUTH_GSS: dprintk("RPC_AUTH_GSS callback secflavor " "not supported!\n"); - READ_BUF(8); + /* gcbp_service */ - dummy = be32_to_cpup(p++); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; + /* gcbp_handle_from_server */ - dummy = be32_to_cpup(p++); - READ_BUF(dummy); - p += XDR_QUADLEN(dummy); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; + if (!xdr_inline_decode(argp->xdr, dummy)) + goto xdr_error; + /* gcbp_handle_from_client */ - READ_BUF(4); - dummy = be32_to_cpup(p++); - READ_BUF(dummy); + if (xdr_stream_decode_u32(argp->xdr, &dummy) < 0) + goto xdr_error; + if (!xdr_inline_decode(argp->xdr, dummy)) + goto xdr_error; break; default: dprintk("Illegal callback secflavor\n"); return nfserr_inval; } } - DECODE_TAIL; + + return nfs_ok; +xdr_error: + return nfserr_bad_xdr; +nomem: + return nfserr_jukebox; } + /* * NFSv4 operation argument decoders */