summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2019-09-10 13:01:35 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2019-09-17 15:14:11 -0400
commitcc204d01262a69218b2d0db5cdea371de85871d9 (patch)
tree7f77b71e876ff7e2007c45be58e29a28f2633ccb
parent98ef77d1aaa7a2f4e1b2a721faa084222021fda7 (diff)
SUNRPC: Dequeue the request from the receive queue while we're re-encoding
Ensure that we dequeue the request from the transport receive queue while we're re-encoding to prevent issues like use-after-free when we release the bvec. Fixes: 7536908982047 ("SUNRPC: Ensure the bvecs are reset when we re-encode...") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Cc: stable@vger.kernel.org # v4.20+ Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--include/linux/sunrpc/xprt.h1
-rw-r--r--net/sunrpc/clnt.c6
-rw-r--r--net/sunrpc/xprt.c54
3 files changed, 35 insertions, 26 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 13e108bcc9eb..d783e15ba898 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -352,6 +352,7 @@ bool xprt_prepare_transmit(struct rpc_task *task);
352void xprt_request_enqueue_transmit(struct rpc_task *task); 352void xprt_request_enqueue_transmit(struct rpc_task *task);
353void xprt_request_enqueue_receive(struct rpc_task *task); 353void xprt_request_enqueue_receive(struct rpc_task *task);
354void xprt_request_wait_receive(struct rpc_task *task); 354void xprt_request_wait_receive(struct rpc_task *task);
355void xprt_request_dequeue_xprt(struct rpc_task *task);
355bool xprt_request_need_retransmit(struct rpc_task *task); 356bool xprt_request_need_retransmit(struct rpc_task *task);
356void xprt_transmit(struct rpc_task *task); 357void xprt_transmit(struct rpc_task *task);
357void xprt_end_transmit(struct rpc_task *task); 358void xprt_end_transmit(struct rpc_task *task);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d8679b6027e9..0359466947e2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1862,6 +1862,7 @@ rpc_xdr_encode(struct rpc_task *task)
1862 req->rq_rbuffer, 1862 req->rq_rbuffer,
1863 req->rq_rcvsize); 1863 req->rq_rcvsize);
1864 1864
1865 req->rq_reply_bytes_recvd = 0;
1865 req->rq_snd_buf.head[0].iov_len = 0; 1866 req->rq_snd_buf.head[0].iov_len = 0;
1866 xdr_init_encode(&xdr, &req->rq_snd_buf, 1867 xdr_init_encode(&xdr, &req->rq_snd_buf,
1867 req->rq_snd_buf.head[0].iov_base, req); 1868 req->rq_snd_buf.head[0].iov_base, req);
@@ -1881,6 +1882,8 @@ call_encode(struct rpc_task *task)
1881 if (!rpc_task_need_encode(task)) 1882 if (!rpc_task_need_encode(task))
1882 goto out; 1883 goto out;
1883 dprint_status(task); 1884 dprint_status(task);
1885 /* Dequeue task from the receive queue while we're encoding */
1886 xprt_request_dequeue_xprt(task);
1884 /* Encode here so that rpcsec_gss can use correct sequence number. */ 1887 /* Encode here so that rpcsec_gss can use correct sequence number. */
1885 rpc_xdr_encode(task); 1888 rpc_xdr_encode(task);
1886 /* Did the encode result in an error condition? */ 1889 /* Did the encode result in an error condition? */
@@ -2501,9 +2504,6 @@ call_decode(struct rpc_task *task)
2501 return; 2504 return;
2502 case -EAGAIN: 2505 case -EAGAIN:
2503 task->tk_status = 0; 2506 task->tk_status = 0;
2504 xdr_free_bvec(&req->rq_rcv_buf);
2505 req->rq_reply_bytes_recvd = 0;
2506 req->rq_rcv_buf.len = 0;
2507 if (task->tk_client->cl_discrtry) 2507 if (task->tk_client->cl_discrtry)
2508 xprt_conditional_disconnect(req->rq_xprt, 2508 xprt_conditional_disconnect(req->rq_xprt,
2509 req->rq_connect_cookie); 2509 req->rq_connect_cookie);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 783748dc5e6f..02d5b2125c07 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1324,6 +1324,36 @@ xprt_request_dequeue_transmit(struct rpc_task *task)
1324} 1324}
1325 1325
1326/** 1326/**
1327 * xprt_request_dequeue_xprt - remove a task from the transmit+receive queue
1328 * @task: pointer to rpc_task
1329 *
1330 * Remove a task from the transmit and receive queues, and ensure that
1331 * it is not pinned by the receive work item.
1332 */
1333void
1334xprt_request_dequeue_xprt(struct rpc_task *task)
1335{
1336 struct rpc_rqst *req = task->tk_rqstp;
1337 struct rpc_xprt *xprt = req->rq_xprt;
1338
1339 if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate) ||
1340 test_bit(RPC_TASK_NEED_RECV, &task->tk_runstate) ||
1341 xprt_is_pinned_rqst(req)) {
1342 spin_lock(&xprt->queue_lock);
1343 xprt_request_dequeue_transmit_locked(task);
1344 xprt_request_dequeue_receive_locked(task);
1345 while (xprt_is_pinned_rqst(req)) {
1346 set_bit(RPC_TASK_MSG_PIN_WAIT, &task->tk_runstate);
1347 spin_unlock(&xprt->queue_lock);
1348 xprt_wait_on_pinned_rqst(req);
1349 spin_lock(&xprt->queue_lock);
1350 clear_bit(RPC_TASK_MSG_PIN_WAIT, &task->tk_runstate);
1351 }
1352 spin_unlock(&xprt->queue_lock);
1353 }
1354}
1355
1356/**
1327 * xprt_request_prepare - prepare an encoded request for transport 1357 * xprt_request_prepare - prepare an encoded request for transport
1328 * @req: pointer to rpc_rqst 1358 * @req: pointer to rpc_rqst
1329 * 1359 *
@@ -1754,28 +1784,6 @@ void xprt_retry_reserve(struct rpc_task *task)
1754 xprt_do_reserve(xprt, task); 1784 xprt_do_reserve(xprt, task);
1755} 1785}
1756 1786
1757static void
1758xprt_request_dequeue_all(struct rpc_task *task, struct rpc_rqst *req)
1759{
1760 struct rpc_xprt *xprt = req->rq_xprt;
1761
1762 if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate) ||
1763 test_bit(RPC_TASK_NEED_RECV, &task->tk_runstate) ||
1764 xprt_is_pinned_rqst(req)) {
1765 spin_lock(&xprt->queue_lock);
1766 xprt_request_dequeue_transmit_locked(task);
1767 xprt_request_dequeue_receive_locked(task);
1768 while (xprt_is_pinned_rqst(req)) {
1769 set_bit(RPC_TASK_MSG_PIN_WAIT, &task->tk_runstate);
1770 spin_unlock(&xprt->queue_lock);
1771 xprt_wait_on_pinned_rqst(req);
1772 spin_lock(&xprt->queue_lock);
1773 clear_bit(RPC_TASK_MSG_PIN_WAIT, &task->tk_runstate);
1774 }
1775 spin_unlock(&xprt->queue_lock);
1776 }
1777}
1778
1779/** 1787/**
1780 * xprt_release - release an RPC request slot 1788 * xprt_release - release an RPC request slot
1781 * @task: task which is finished with the slot 1789 * @task: task which is finished with the slot
@@ -1795,7 +1803,7 @@ void xprt_release(struct rpc_task *task)
1795 } 1803 }
1796 1804
1797 xprt = req->rq_xprt; 1805 xprt = req->rq_xprt;
1798 xprt_request_dequeue_all(task, req); 1806 xprt_request_dequeue_xprt(task);
1799 spin_lock(&xprt->transport_lock); 1807 spin_lock(&xprt->transport_lock);
1800 xprt->ops->release_xprt(xprt, task); 1808 xprt->ops->release_xprt(xprt, task);
1801 if (xprt->ops->release_request) 1809 if (xprt->ops->release_request)