xprtrdma: rpcrdma_inline_fixup() overruns the receive page list
authorChuck Lever <chuck.lever@oracle.com>
Wed, 29 Jun 2016 17:54:33 +0000 (13:54 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 11 Jul 2016 19:50:43 +0000 (15:50 -0400)
When the remaining length of an incoming reply is longer than the
XDR buf's page_len, switch over to the tail iovec instead of
copying more than page_len bytes into the page list.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
net/sunrpc/xprtrdma/rpc_rdma.c

index f60d229b78b49bad4ed62123638b2e3288636921..e3560c2e2271a3f359ae6497a7439565a7670528 100644 (file)
@@ -773,12 +773,17 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
        page_base &= ~PAGE_MASK;
 
        if (copy_len && rqst->rq_rcv_buf.page_len) {
-               npages = PAGE_ALIGN(page_base +
-                       rqst->rq_rcv_buf.page_len) >> PAGE_SHIFT;
+               int pagelist_len;
+
+               pagelist_len = rqst->rq_rcv_buf.page_len;
+               if (pagelist_len > copy_len)
+                       pagelist_len = copy_len;
+               npages = PAGE_ALIGN(page_base + pagelist_len) >> PAGE_SHIFT;
                for (; i < npages; i++) {
                        curlen = PAGE_SIZE - page_base;
-                       if (curlen > copy_len)
-                               curlen = copy_len;
+                       if (curlen > pagelist_len)
+                               curlen = pagelist_len;
+
                        dprintk("RPC:       %s: page %d"
                                " srcp 0x%p len %d curlen %d\n",
                                __func__, i, srcp, copy_len, curlen);
@@ -788,7 +793,8 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
                        kunmap_atomic(destp);
                        srcp += curlen;
                        copy_len -= curlen;
-                       if (copy_len == 0)
+                       pagelist_len -= curlen;
+                       if (!pagelist_len)
                                break;
                        page_base = 0;
                }
This page took 0.026528 seconds and 5 git commands to generate.