Skip to content

Commit 649a692

Browse files
committed
SUNRPC: Convert RPC Reply header encoding to use xdr_stream
The main part of RPC header encoding and the formation of error responses are now done using the xdr_stream helpers. Bounds checking before each XDR data item is encoded makes the server's encoding path safer against accidental buffer overflows. Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent fcef2af commit 649a692

File tree

1 file changed

+25
-25
lines changed

1 file changed

+25
-25
lines changed

net/sunrpc/svc.c

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,13 +1227,14 @@ EXPORT_SYMBOL_GPL(svc_generic_init_request);
12271227
static int
12281228
svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
12291229
{
1230+
struct xdr_stream *xdr = &rqstp->rq_res_stream;
12301231
struct svc_program *progp;
12311232
const struct svc_procedure *procp = NULL;
12321233
struct svc_serv *serv = rqstp->rq_server;
12331234
struct svc_process_info process;
12341235
__be32 *p, *statp;
12351236
int auth_res, rc;
1236-
__be32 *reply_statp;
1237+
unsigned int aoffset;
12371238

12381239
/* Will be turned off by GSS integrity and privacy services */
12391240
set_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
@@ -1242,17 +1243,17 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
12421243
clear_bit(RQ_DROPME, &rqstp->rq_flags);
12431244

12441245
/* Construct the first words of the reply: */
1245-
svc_putu32(resv, rqstp->rq_xid);
1246-
svc_putnl(resv, RPC_REPLY);
1247-
reply_statp = resv->iov_base + resv->iov_len;
1246+
svcxdr_init_encode(rqstp);
1247+
xdr_stream_encode_be32(xdr, rqstp->rq_xid);
1248+
xdr_stream_encode_be32(xdr, rpc_reply);
12481249

12491250
p = xdr_inline_decode(&rqstp->rq_arg_stream, XDR_UNIT * 4);
12501251
if (unlikely(!p))
12511252
goto err_short_len;
12521253
if (*p++ != cpu_to_be32(RPC_VERSION))
12531254
goto err_bad_rpc;
12541255

1255-
svc_putnl(resv, 0); /* ACCEPT */
1256+
xdr_stream_encode_be32(xdr, rpc_msg_accepted);
12561257

12571258
rqstp->rq_prog = be32_to_cpup(p++);
12581259
rqstp->rq_vers = be32_to_cpup(p++);
@@ -1262,8 +1263,6 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
12621263
if (rqstp->rq_prog == progp->pg_prog)
12631264
break;
12641265

1265-
svcxdr_init_encode(rqstp);
1266-
12671266
/*
12681267
* Decode auth data, and add verifier to reply buffer.
12691268
* We do this before anything else in order to get a decent
@@ -1314,6 +1313,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
13141313
serv->sv_stats->rpccnt++;
13151314
trace_svc_process(rqstp, progp->pg_name);
13161315

1316+
aoffset = xdr_stream_pos(xdr);
13171317
statp = xdr_reserve_space(&rqstp->rq_res_stream, XDR_UNIT);
13181318
*statp = rpc_success;
13191319

@@ -1332,9 +1332,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
13321332
if (rqstp->rq_auth_stat != rpc_auth_ok)
13331333
goto err_bad_auth;
13341334

1335-
/* Check RPC status result */
13361335
if (*statp != rpc_success)
1337-
resv->iov_len = ((void*)statp) - resv->iov_base + 4;
1336+
xdr_truncate_encode(xdr, aoffset);
13381337

13391338
if (procp->pc_encode == NULL)
13401339
goto dropit;
@@ -1364,56 +1363,57 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *resv)
13641363

13651364
err_bad_rpc:
13661365
serv->sv_stats->rpcbadfmt++;
1367-
svc_putnl(resv, 1); /* REJECT */
1368-
svc_putnl(resv, 0); /* RPC_MISMATCH */
1369-
svc_putnl(resv, 2); /* Only RPCv2 supported */
1370-
svc_putnl(resv, 2);
1366+
xdr_stream_encode_u32(xdr, RPC_MSG_DENIED);
1367+
xdr_stream_encode_u32(xdr, RPC_MISMATCH);
1368+
/* Only RPCv2 supported */
1369+
xdr_stream_encode_u32(xdr, RPC_VERSION);
1370+
xdr_stream_encode_u32(xdr, RPC_VERSION);
13711371
goto sendit;
13721372

13731373
err_bad_auth:
13741374
dprintk("svc: authentication failed (%d)\n",
13751375
be32_to_cpu(rqstp->rq_auth_stat));
13761376
serv->sv_stats->rpcbadauth++;
1377-
/* Restore write pointer to location of accept status: */
1378-
xdr_ressize_check(rqstp, reply_statp);
1379-
svc_putnl(resv, 1); /* REJECT */
1380-
svc_putnl(resv, 1); /* AUTH_ERROR */
1381-
svc_putu32(resv, rqstp->rq_auth_stat); /* status */
1377+
/* Restore write pointer to location of reply status: */
1378+
xdr_truncate_encode(xdr, XDR_UNIT * 2);
1379+
xdr_stream_encode_u32(xdr, RPC_MSG_DENIED);
1380+
xdr_stream_encode_u32(xdr, RPC_AUTH_ERROR);
1381+
xdr_stream_encode_be32(xdr, rqstp->rq_auth_stat);
13821382
goto sendit;
13831383

13841384
err_bad_prog:
13851385
dprintk("svc: unknown program %d\n", rqstp->rq_prog);
13861386
serv->sv_stats->rpcbadfmt++;
1387-
svc_putnl(resv, RPC_PROG_UNAVAIL);
1387+
xdr_stream_encode_u32(xdr, RPC_PROG_UNAVAIL);
13881388
goto sendit;
13891389

13901390
err_bad_vers:
13911391
svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n",
13921392
rqstp->rq_vers, rqstp->rq_prog, progp->pg_name);
13931393

13941394
serv->sv_stats->rpcbadfmt++;
1395-
svc_putnl(resv, RPC_PROG_MISMATCH);
1396-
svc_putnl(resv, process.mismatch.lovers);
1397-
svc_putnl(resv, process.mismatch.hivers);
1395+
xdr_stream_encode_u32(xdr, RPC_PROG_MISMATCH);
1396+
xdr_stream_encode_u32(xdr, process.mismatch.lovers);
1397+
xdr_stream_encode_u32(xdr, process.mismatch.hivers);
13981398
goto sendit;
13991399

14001400
err_bad_proc:
14011401
svc_printk(rqstp, "unknown procedure (%d)\n", rqstp->rq_proc);
14021402

14031403
serv->sv_stats->rpcbadfmt++;
1404-
svc_putnl(resv, RPC_PROC_UNAVAIL);
1404+
xdr_stream_encode_u32(xdr, RPC_PROC_UNAVAIL);
14051405
goto sendit;
14061406

14071407
err_garbage_args:
14081408
svc_printk(rqstp, "failed to decode RPC header\n");
14091409

14101410
serv->sv_stats->rpcbadfmt++;
1411-
svc_putnl(resv, RPC_GARBAGE_ARGS);
1411+
xdr_stream_encode_u32(xdr, RPC_GARBAGE_ARGS);
14121412
goto sendit;
14131413

14141414
err_system_err:
14151415
serv->sv_stats->rpcbadfmt++;
1416-
svc_putnl(resv, RPC_SYSTEM_ERR);
1416+
xdr_stream_encode_u32(xdr, RPC_SYSTEM_ERR);
14171417
goto sendit;
14181418
}
14191419

0 commit comments

Comments
 (0)