Commit 1a994408 authored by Chuck Lever's avatar Chuck Lever

NFSD: Replace READ* macros in nfsd4_decode_cb_sec()

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent a4a80c15
...@@ -212,6 +212,25 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) ...@@ -212,6 +212,25 @@ static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
* NFSv4 basic data type decoders * NFSv4 basic data type decoders
*/ */
/*
* This helper handles variable-length opaques which belong to protocol
* elements that this implementation does not support.
*/
static __be32
nfsd4_decode_ignored_string(struct nfsd4_compoundargs *argp, u32 maxlen)
{
u32 len;
if (xdr_stream_decode_u32(argp->xdr, &len) < 0)
return nfserr_bad_xdr;
if (maxlen && len > maxlen)
return nfserr_bad_xdr;
if (!xdr_inline_decode(argp->xdr, len))
return nfserr_bad_xdr;
return nfs_ok;
}
static __be32 static __be32
nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o) nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
{ {
...@@ -645,87 +664,117 @@ nfsd4_decode_state_owner4(struct nfsd4_compoundargs *argp, ...@@ -645,87 +664,117 @@ nfsd4_decode_state_owner4(struct nfsd4_compoundargs *argp,
return nfsd4_decode_opaque(argp, owner); return nfsd4_decode_opaque(argp, owner);
} }
static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs) /* Defined in Appendix A of RFC 5531 */
static __be32
nfsd4_decode_authsys_parms(struct nfsd4_compoundargs *argp,
struct nfsd4_cb_sec *cbs)
{ {
DECODE_HEAD; u32 stamp, gidcount, uid, gid;
__be32 *p, status;
if (xdr_stream_decode_u32(argp->xdr, &stamp) < 0)
return nfserr_bad_xdr;
/* machine name */
status = nfsd4_decode_ignored_string(argp, 255);
if (status)
return status;
if (xdr_stream_decode_u32(argp->xdr, &uid) < 0)
return nfserr_bad_xdr;
if (xdr_stream_decode_u32(argp->xdr, &gid) < 0)
return nfserr_bad_xdr;
if (xdr_stream_decode_u32(argp->xdr, &gidcount) < 0)
return nfserr_bad_xdr;
if (gidcount > 16)
return nfserr_bad_xdr;
p = xdr_inline_decode(argp->xdr, gidcount << 2);
if (!p)
return nfserr_bad_xdr;
if (cbs->flavor == (u32)(-1)) {
struct user_namespace *userns = nfsd_user_namespace(argp->rqstp); struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
u32 dummy, uid, gid;
char *machine_name; kuid_t kuid = make_kuid(userns, uid);
int i; kgid_t kgid = make_kgid(userns, gid);
int nr_secflavs; if (uid_valid(kuid) && gid_valid(kgid)) {
cbs->uid = kuid;
cbs->gid = kgid;
cbs->flavor = RPC_AUTH_UNIX;
} else {
dprintk("RPC_AUTH_UNIX with invalid uid or gid, ignoring!\n");
}
}
return nfs_ok;
}
static __be32
nfsd4_decode_gss_cb_handles4(struct nfsd4_compoundargs *argp,
struct nfsd4_cb_sec *cbs)
{
__be32 status;
u32 service;
dprintk("RPC_AUTH_GSS callback secflavor not supported!\n");
if (xdr_stream_decode_u32(argp->xdr, &service) < 0)
return nfserr_bad_xdr;
if (service < RPC_GSS_SVC_NONE || service > RPC_GSS_SVC_PRIVACY)
return nfserr_bad_xdr;
/* gcbp_handle_from_server */
status = nfsd4_decode_ignored_string(argp, 0);
if (status)
return status;
/* gcbp_handle_from_client */
status = nfsd4_decode_ignored_string(argp, 0);
if (status)
return status;
return nfs_ok;
}
/* a counted array of callback_sec_parms4 items */
static __be32
nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
{
u32 i, secflavor, nr_secflavs;
__be32 status;
/* callback_sec_params4 */ /* callback_sec_params4 */
READ_BUF(4); if (xdr_stream_decode_u32(argp->xdr, &nr_secflavs) < 0)
nr_secflavs = be32_to_cpup(p++); return nfserr_bad_xdr;
if (nr_secflavs) if (nr_secflavs)
cbs->flavor = (u32)(-1); cbs->flavor = (u32)(-1);
else else
/* Is this legal? Be generous, take it to mean AUTH_NONE: */ /* Is this legal? Be generous, take it to mean AUTH_NONE: */
cbs->flavor = 0; cbs->flavor = 0;
for (i = 0; i < nr_secflavs; ++i) { for (i = 0; i < nr_secflavs; ++i) {
READ_BUF(4); if (xdr_stream_decode_u32(argp->xdr, &secflavor) < 0)
dummy = be32_to_cpup(p++); return nfserr_bad_xdr;
switch (dummy) { switch (secflavor) {
case RPC_AUTH_NULL: case RPC_AUTH_NULL:
/* Nothing to read */ /* void */
if (cbs->flavor == (u32)(-1)) if (cbs->flavor == (u32)(-1))
cbs->flavor = RPC_AUTH_NULL; cbs->flavor = RPC_AUTH_NULL;
break; break;
case RPC_AUTH_UNIX: case RPC_AUTH_UNIX:
READ_BUF(8); status = nfsd4_decode_authsys_parms(argp, cbs);
/* stamp */ if (status)
dummy = be32_to_cpup(p++); return status;
/* machine name */
dummy = be32_to_cpup(p++);
READ_BUF(dummy);
SAVEMEM(machine_name, dummy);
/* uid, gid */
READ_BUF(8);
uid = be32_to_cpup(p++);
gid = be32_to_cpup(p++);
/* more gids */
READ_BUF(4);
dummy = be32_to_cpup(p++);
READ_BUF(dummy * 4);
if (cbs->flavor == (u32)(-1)) {
kuid_t kuid = make_kuid(userns, uid);
kgid_t kgid = make_kgid(userns, gid);
if (uid_valid(kuid) && gid_valid(kgid)) {
cbs->uid = kuid;
cbs->gid = kgid;
cbs->flavor = RPC_AUTH_UNIX;
} else {
dprintk("RPC_AUTH_UNIX with invalid"
"uid or gid ignoring!\n");
}
}
break; break;
case RPC_AUTH_GSS: case RPC_AUTH_GSS:
dprintk("RPC_AUTH_GSS callback secflavor " status = nfsd4_decode_gss_cb_handles4(argp, cbs);
"not supported!\n"); if (status)
READ_BUF(8); return status;
/* gcbp_service */
dummy = be32_to_cpup(p++);
/* gcbp_handle_from_server */
dummy = be32_to_cpup(p++);
READ_BUF(dummy);
p += XDR_QUADLEN(dummy);
/* gcbp_handle_from_client */
READ_BUF(4);
dummy = be32_to_cpup(p++);
READ_BUF(dummy);
break; break;
default: default:
dprintk("Illegal callback secflavor\n");
return nfserr_inval; return nfserr_inval;
} }
} }
DECODE_TAIL;
return nfs_ok;
} }
/* /*
* NFSv4 operation argument decoders * NFSv4 operation argument decoders
*/ */
......
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