svcrdma: backchannel cannot share a page for send and rcv buffers
authorChuck Lever <chuck.lever@oracle.com>
Sat, 29 Oct 2016 02:22:33 +0000 (22:22 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 1 Nov 2016 19:23:58 +0000 (15:23 -0400)
The underlying transport releases the page pointed to by rq_buffer
during xprt_rdma_bc_send_request. When the backchannel reply arrives,
rq_rbuffer then points to freed memory.

Fixes: 68778945e46f ('SUNRPC: Separate buffer pointers for RPC ...')
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/xprtrdma/svc_rdma_backchannel.c

index fc4535ead7c2293490d91815596412b784d1c9e0..20027f8de129e61faba9037d552eb826ecc34ae4 100644 (file)
@@ -177,19 +177,26 @@ xprt_rdma_bc_allocate(struct rpc_task *task)
                return -EINVAL;
        }
 
+       /* svc_rdma_sendto releases this page */
        page = alloc_page(RPCRDMA_DEF_GFP);
        if (!page)
                return -ENOMEM;
-
        rqst->rq_buffer = page_address(page);
-       rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize;
+
+       rqst->rq_rbuffer = kmalloc(rqst->rq_rcvsize, RPCRDMA_DEF_GFP);
+       if (!rqst->rq_rbuffer) {
+               put_page(page);
+               return -ENOMEM;
+       }
        return 0;
 }
 
 static void
 xprt_rdma_bc_free(struct rpc_task *task)
 {
-       /* No-op: ctxt and page have already been freed. */
+       struct rpc_rqst *rqst = task->tk_rqstp;
+
+       kfree(rqst->rq_rbuffer);
 }
 
 static int