diff options
| author | Chuck Lever <chuck.lever@oracle.com> | 2016-10-28 22:22:33 -0400 |
|---|---|---|
| committer | J. Bruce Fields <bfields@redhat.com> | 2016-11-01 15:23:58 -0400 |
| commit | 8d42629be0cb6c58a5c77cd02e47974c0e724e63 (patch) | |
| tree | 3d2146cfe4432350fb9b795cc38ff7c0f5602216 /net/sunrpc | |
| parent | 18e601d6adae5042f82d105ccd3d4498050f2ebf (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.c | 13 |
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 | ||
| 189 | static void | 194 | static void |
| 190 | xprt_rdma_bc_free(struct rpc_task *task) | 195 | xprt_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 | ||
| 195 | static int | 202 | static int |
