<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:DengXian;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"\@DengXian";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;
        mso-ligatures:none;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="EN-SG" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal">Previously, if cm fails after the rio has been created, the rdma_cm_id</p>
<p class="MsoNormal">would not be destroyed immediately. However the cm_id->context could</p>
<p class="MsoNormal">still point to rc->id which would no longer be valid. This dealy create</p>
<p class="MsoNormal">a window during which cm_id->context holds an illegal pointer. If an RMDA</p>
<p class="MsoNormal">cm event arrives during this window, an illegal pointer dereference will</p>
<p class="MsoNormal">happen, thus crashing the system.</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Fixes</p>
<p class="MsoNormal">https://pmc.acronis.work/browse/VSTOR-79838</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Signed-off-by: Liu Kui <kui.liu@acronis.com></p>
<p class="MsoNormal">---</p>
<p class="MsoNormal">fs/fuse/kio/pcs/pcs_rdma_conn.c | 16 +++++++++-------</p>
<p class="MsoNormal">fs/fuse/kio/pcs/pcs_rdma_io.c | 29 ++++++++++++++++++++++-------</p>
<p class="MsoNormal">fs/fuse/kio/pcs/pcs_rdma_io.h | 2 +-</p>
<p class="MsoNormal">3 files changed, 32 insertions(+), 15 deletions(-)</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">diff --git a/fs/fuse/kio/pcs/pcs_rdma_conn.c b/fs/fuse/kio/pcs/pcs_rdma_conn.c</p>
<p class="MsoNormal">index 96fc2b1ed281..846106a59d50 100644</p>
<p class="MsoNormal">--- a/fs/fuse/kio/pcs/pcs_rdma_conn.c</p>
<p class="MsoNormal">+++ b/fs/fuse/kio/pcs/pcs_rdma_conn.c</p>
<p class="MsoNormal">@@ -77,7 +77,6 @@ static int pcs_rdma_cm_event_handler(struct rdma_cm_id *cmid,</p>
<p class="MsoNormal"> complete(&rc->cm_done);</p>
<p class="MsoNormal"> break;</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal">- rc->cmid = NULL;</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> conn_param_init(&conn_param, &rc->rio->conn_req, cmid);</p>
<p class="MsoNormal"> if (rdma_connect_locked(cmid, &conn_param)) {</p>
<p class="MsoNormal">@@ -87,10 +86,6 @@ static int pcs_rdma_cm_event_handler(struct rdma_cm_id *cmid,</p>
<p class="MsoNormal"> break;</p>
<p class="MsoNormal"> case RDMA_CM_EVENT_ESTABLISHED:</p>
<p class="MsoNormal"> cmid->context = &rc->rio->id;</p>
<p class="MsoNormal">- if (pcs_rdma_established(rc->rio)) {</p>
<p class="MsoNormal">- TRACE("pcs_rdma_established failed, rio: 0x%p\n", rc->rio);</p>
<p class="MsoNormal">- rc->cm_event = RDMA_CM_EVENT_REJECTED;</p>
<p class="MsoNormal">- }</p>
<p class="MsoNormal"> complete(&rc->cm_done);</p>
<p class="MsoNormal"> break;</p>
<p class="MsoNormal"> case RDMA_CM_EVENT_REJECTED:</p>
<p class="MsoNormal">@@ -166,6 +161,14 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)</p>
<p class="MsoNormal"> ep->flags |= PCS_RPC_F_PEER_ID;</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> ep->state = PCS_RPC_AUTH;</p>
<p class="MsoNormal">+</p>
<p class="MsoNormal">+ /* setup rxs */</p>
<p class="MsoNormal">+ if (pcs_rdma_setup_rxs((rc.rio))) {</p>
<p class="MsoNormal">+ TRACE("pcs_rdma_setup_rxs failed, rio: 0x%p\n", rc.rio);</p>
<p class="MsoNormal">+ pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);</p>
<p class="MsoNormal">+ goto fail;</p>
<p class="MsoNormal">+ }</p>
<p class="MsoNormal">+</p>
<p class="MsoNormal"> ret = rpc_client_start_auth(ep, PCS_AUTH_DIGEST,</p>
<p class="MsoNormal"> cc_from_rpc(ep->eng)->cluster_name);</p>
<p class="MsoNormal"> if (ret < 0) {</p>
<p class="MsoNormal">@@ -186,8 +189,7 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)</p>
<p class="MsoNormal">fail_cm:</p>
<p class="MsoNormal"> if (rc.rio)</p>
<p class="MsoNormal"> pcs_rdma_destroy(rc.rio);</p>
<p class="MsoNormal">- if (rc.cmid)</p>
<p class="MsoNormal">- rdma_destroy_id(rc.cmid);</p>
<p class="MsoNormal">+ rdma_destroy_id(rc.cmid);</p>
<p class="MsoNormal">fail:</p>
<p class="MsoNormal"> pcs_rpc_reset(ep);</p>
<p class="MsoNormal"> return;</p>
<p class="MsoNormal">diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.c b/fs/fuse/kio/pcs/pcs_rdma_io.c</p>
<p class="MsoNormal">index 62d138c8b611..622ce72c5a85 100644</p>
<p class="MsoNormal">--- a/fs/fuse/kio/pcs/pcs_rdma_io.c</p>
<p class="MsoNormal">+++ b/fs/fuse/kio/pcs/pcs_rdma_io.c</p>
<p class="MsoNormal">@@ -1322,7 +1322,7 @@ struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,</p>
<p class="MsoNormal"> return NULL;</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">-int pcs_rdma_established(struct pcs_rdmaio *rio)</p>
<p class="MsoNormal">+int pcs_rdma_setup_rxs(struct pcs_rdmaio *rio)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal"> struct rio_rx *rx;</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">@@ -1444,20 +1444,35 @@ static void rio_destroy(struct work_struct *work)</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">static DECLARE_WORK(rio_destroy_work, rio_destroy);</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">+/*</p>
<p class="MsoNormal">+ * This is only used in case cm error happens during establishing</p>
<p class="MsoNormal">+ * a connection. We need to destroy the rio immediately such that</p>
<p class="MsoNormal">+ * the rdma_cm_id can be destroyed immediately afterwards.</p>
<p class="MsoNormal">+ */</p>
<p class="MsoNormal">void pcs_rdma_destroy(struct pcs_rdmaio *rio)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal">- struct pcs_netio *netio = &rio->netio;</p>
<p class="MsoNormal">- struct pcs_rpc *ep = netio->parent;</p>
<p class="MsoNormal">+ struct pcs_rpc *ep = rio->netio.parent;</p>
<p class="MsoNormal">+ int i;</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> TRACE("rio: 0x%p\n", rio);</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> BUG_ON(!mutex_is_locked(&ep->mutex));</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">- netio->eof = NULL;</p>
<p class="MsoNormal">- rio_abort(rio, PCS_ERR_NET_ABORT);</p>
<p class="MsoNormal">+ rio->rio_state = RIO_STATE_ABORTED;</p>
<p class="MsoNormal">+ rio->rio_error = PCS_ERR_NET_ABORT;</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">- if (llist_add(&rio->destroy_node, &rio_destroy_list))</p>
<p class="MsoNormal">- queue_work(pcs_cleanup_wq, &rio_destroy_work);</p>
<p class="MsoNormal">+ rdma_disconnect(rio->cmid);</p>
<p class="MsoNormal">+</p>
<p class="MsoNormal">+ rdma_destroy_qp(rio->cmid);</p>
<p class="MsoNormal">+ ib_destroy_cq(rio->cq);</p>
<p class="MsoNormal">+</p>
<p class="MsoNormal">+ pcs_rdma_device_destroy(rio->dev);</p>
<p class="MsoNormal">+ for (i = 0; i < rio->recv_queue_depth; i++)</p>
<p class="MsoNormal">+ rio_fini_rx(rio->rx_descs + i, rio->cmid->device);</p>
<p class="MsoNormal">+ kfree(rio->rx_descs);</p>
<p class="MsoNormal">+</p>
<p class="MsoNormal">+ pcs_rpc_put(ep);</p>
<p class="MsoNormal">+ kfree(rio);</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void pcs_rdma_ioconn_destruct(struct pcs_ioconn *ioconn)</p>
<p class="MsoNormal">diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.h b/fs/fuse/kio/pcs/pcs_rdma_io.h</p>
<p class="MsoNormal">index 18962208e4a2..87cae3764f23 100644</p>
<p class="MsoNormal">--- a/fs/fuse/kio/pcs/pcs_rdma_io.h</p>
<p class="MsoNormal">+++ b/fs/fuse/kio/pcs/pcs_rdma_io.h</p>
<p class="MsoNormal">@@ -113,7 +113,7 @@ struct pcs_rdmaio</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,</p>
<p class="MsoNormal"> int queue_depth, struct pcs_rpc *ep);</p>
<p class="MsoNormal">-int pcs_rdma_established(struct pcs_rdmaio *rio);</p>
<p class="MsoNormal">+int pcs_rdma_setup_rxs(struct pcs_rdmaio *rio);</p>
<p class="MsoNormal">void pcs_rdma_destroy(struct pcs_rdmaio *rio);</p>
<p class="MsoNormal">void pcs_rdma_ioconn_destruct(struct pcs_ioconn *ioconn);</p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">--</p>
<p class="MsoNormal">2.32.0 (Apple Git-132)</p>
</div>
</body>
</html>