aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2016-10-28 22:22:33 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-11-01 15:23:58 -0400
commit8d42629be0cb6c58a5c77cd02e47974c0e724e63 (patch)
tree3d2146cfe4432350fb9b795cc38ff7c0f5602216 /net/sunrpc
parent18e601d6adae5042f82d105ccd3d4498050f2ebf (diff)
svcrdma: backchannel cannot share a page for send and rcv buffers
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>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_backchannel.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
index fc4535ead7c2..20027f8de129 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
@@ -177,19 +177,26 @@ xprt_rdma_bc_allocate(struct rpc_task *task)
177 return -EINVAL; 177 return -EINVAL;
178 } 178 }
179 179
180 /* svc_rdma_sendto releases this page */
180 page = alloc_page(RPCRDMA_DEF_GFP); 181 page = alloc_page(RPCRDMA_DEF_GFP);
181 if (!page) 182 if (!page)
182 return -ENOMEM; 183 return -ENOMEM;
183
184 rqst->rq_buffer = page_address(page); 184 rqst->rq_buffer = page_address(page);
185 rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize; 185
186 rqst->rq_rbuffer = kmalloc(rqst->rq_rcvsize, RPCRDMA_DEF_GFP);
187 if (!rqst->rq_rbuffer) {
188 put_page(page);
189 return -ENOMEM;
190 }
186 return 0; 191 return 0;
187} 192}
188 193
189static void 194static void
190xprt_rdma_bc_free(struct rpc_task *task) 195xprt_rdma_bc_free(struct rpc_task *task)
191{ 196{
192 /* No-op: ctxt and page have already been freed. */ 197 struct rpc_rqst *rqst = task->tk_rqstp;
198
199 kfree(rqst->rq_rbuffer);
193} 200}
194 201
195static int 202static int