diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2023-01-02 12:07:52 -0500 |
---|---|---|
committer | Chuck Lever <chuck.lever@oracle.com> | 2023-02-20 09:20:21 -0500 |
commit | 163cdfca341b76c958567ae0966bd3575c5c6192 (patch) | |
tree | b8176af6fdba7d73da0a41b95d84cb074e0e4a94 /net | |
parent | 4119bd0306652776cb0b7caa3aea5b2a93aecb89 (diff) |
SUNRPC: Decode most of RPC header with xdr_stream
Done as part of hardening the server-side RPC header decoding path.
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svc.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index c3c80d2709fb..2cc804932543 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1231,17 +1231,13 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) const struct svc_procedure *procp = NULL; struct svc_serv *serv = rqstp->rq_server; struct svc_process_info process; - __be32 *statp; - u32 vers; + __be32 *p, *statp; __be32 rpc_stat; int auth_res, rc; __be32 *reply_statp; rpc_stat = rpc_success; - if (argv->iov_len < 6*4) - goto err_short_len; - /* Will be turned off by GSS integrity and privacy services */ set_bit(RQ_SPLICE_OK, &rqstp->rq_flags); /* Will be turned off only when NFSv4 Sessions are used */ @@ -1253,15 +1249,18 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) svc_putnl(resv, RPC_REPLY); reply_statp = resv->iov_base + resv->iov_len; - vers = svc_getnl(argv); - if (vers != 2) /* RPC version number */ + svcxdr_init_decode(rqstp); + p = xdr_inline_decode(&rqstp->rq_arg_stream, XDR_UNIT * 4); + if (unlikely(!p)) + goto err_short_len; + if (*p++ != cpu_to_be32(RPC_VERSION)) goto err_bad_rpc; svc_putnl(resv, 0); /* ACCEPT */ - rqstp->rq_prog = svc_getnl(argv); /* program number */ - rqstp->rq_vers = svc_getnl(argv); /* version number */ - rqstp->rq_proc = svc_getnl(argv); /* procedure number */ + rqstp->rq_prog = be32_to_cpup(p++); + rqstp->rq_vers = be32_to_cpup(p++); + rqstp->rq_proc = be32_to_cpup(p); for (progp = serv->sv_program; progp; progp = progp->pg_next) if (rqstp->rq_prog == progp->pg_prog) @@ -1272,7 +1271,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) * We do this before anything else in order to get a decent * auth verifier. */ - svcxdr_init_decode(rqstp); auth_res = svc_authenticate(rqstp); /* Also give the program a chance to reject this call: */ if (auth_res == SVC_OK && progp) |