Skip to content

Commit 61edbcb

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
svcrdma: rc_position sanity checking
An RPC/RDMA client may send large RPC arguments via a read list. This is a list of scatter/gather elements which convey RPC call arguments too large to fit in a small RDMA SEND. Each entry in the read list has a "position" field, whose value is the byte offset in the XDR stream where the data in that entry is to be inserted. Entries which share the same "position" value make up the same RPC argument. The receiver inserts entries with the same position field value in list order into the XDR stream. Currently the Linux NFS/RDMA server cannot handle receiving read chunks in more than one position, mostly because no current client sends read lists with elements in more than one position. As a sanity check, ensure that all received chunks have the same "rc_position." Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Steve Wise <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent e545241 commit 61edbcb

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
365365
int page_no, ret;
366366
struct rpcrdma_read_chunk *ch;
367367
u32 handle, page_offset, byte_count;
368+
u32 position;
368369
u64 rs_offset;
369370
bool last;
370371

@@ -389,10 +390,17 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
389390
head->arg.len = rqstp->rq_arg.len;
390391
head->arg.buflen = rqstp->rq_arg.buflen;
391392

392-
page_no = 0; page_offset = 0;
393-
for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
394-
ch->rc_discrim != 0; ch++) {
395-
handle = be32_to_cpu(ch->rc_target.rs_handle);
393+
ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
394+
position = be32_to_cpu(ch->rc_position);
395+
396+
ret = 0;
397+
page_no = 0;
398+
page_offset = 0;
399+
for (; ch->rc_discrim != xdr_zero; ch++) {
400+
if (be32_to_cpu(ch->rc_position) != position)
401+
goto err;
402+
403+
handle = be32_to_cpu(ch->rc_target.rs_handle),
396404
byte_count = be32_to_cpu(ch->rc_target.rs_length);
397405
xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset,
398406
&rs_offset);

0 commit comments

Comments
 (0)