aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2023-01-02 12:07:52 -0500
committerChuck Lever <chuck.lever@oracle.com>2023-02-20 09:20:21 -0500
commit163cdfca341b76c958567ae0966bd3575c5c6192 (patch)
treeb8176af6fdba7d73da0a41b95d84cb074e0e4a94 /net
parent4119bd0306652776cb0b7caa3aea5b2a93aecb89 (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.c20
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)