The commit is pushed to "branch-rh9-5.14.0-284.25.1.vz9.27.x-ovz" and will 
appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-284.25.1.vz9.27.5
------>
commit 47f1df754353d2e6ae0402d2e15b58351fa6e18f
Author: Liu Kui <kui....@acronis.com>
Date:   Tue Jan 2 16:53:08 2024 +0800

    fs/fuse kio: destroy rdma_cm_id immediately in case cm fails during 
connection establishment
    
    Previously, if cm fails after the rio has been created, the rdma_cm_id
    would not be destroyed immediately. However the cm_id->context could
    still point to rc->id which would no longer be valid. This dealy create
    a window during which cm_id->context holds an illegal pointer. If an RMDA
    cm event arrives during this window, an illegal pointer dereference will
    happen, thus crashing the system.
    
    https://pmc.acronis.work/browse/VSTOR-79838
    
    Signed-off-by: Liu Kui <kui....@acronis.com>
    
    Feature: vStorage
---
 fs/fuse/kio/pcs/pcs_rdma_conn.c | 16 +++++++++-------
 fs/fuse/kio/pcs/pcs_rdma_io.c   | 29 ++++++++++++++++++++++-------
 fs/fuse/kio/pcs/pcs_rdma_io.h   |  2 +-
 3 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/fs/fuse/kio/pcs/pcs_rdma_conn.c b/fs/fuse/kio/pcs/pcs_rdma_conn.c
index 96fc2b1ed281..846106a59d50 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_conn.c
+++ b/fs/fuse/kio/pcs/pcs_rdma_conn.c
@@ -77,7 +77,6 @@ static int pcs_rdma_cm_event_handler(struct rdma_cm_id *cmid,
                                complete(&rc->cm_done);
                                break;
                        }
-                       rc->cmid = NULL;
 
                        conn_param_init(&conn_param, &rc->rio->conn_req, cmid);
                        if (rdma_connect_locked(cmid, &conn_param)) {
@@ -87,10 +86,6 @@ static int pcs_rdma_cm_event_handler(struct rdma_cm_id *cmid,
                        break;
                case RDMA_CM_EVENT_ESTABLISHED:
                        cmid->context = &rc->rio->id;
-                       if (pcs_rdma_established(rc->rio)) {
-                               TRACE("pcs_rdma_established failed, rio: 
0x%p\n", rc->rio);
-                               rc->cm_event = RDMA_CM_EVENT_REJECTED;
-                       }
                        complete(&rc->cm_done);
                        break;
                case RDMA_CM_EVENT_REJECTED:
@@ -166,6 +161,14 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)
                ep->flags |= PCS_RPC_F_PEER_ID;
 
        ep->state = PCS_RPC_AUTH;
+
+       /* setup rxs */
+       if (pcs_rdma_setup_rxs((rc.rio))) {
+               TRACE("pcs_rdma_setup_rxs failed, rio: 0x%p\n", rc.rio);
+               pcs_rpc_report_error(ep, PCS_RPC_ERR_CONNECT_ERROR);
+               goto fail;
+       }
+
        ret = rpc_client_start_auth(ep, PCS_AUTH_DIGEST,
                                    cc_from_rpc(ep->eng)->cluster_name);
        if (ret < 0) {
@@ -186,8 +189,7 @@ void pcs_rdmaconnect_start(struct pcs_rpc *ep)
 fail_cm:
        if (rc.rio)
                pcs_rdma_destroy(rc.rio);
-       if (rc.cmid)
-               rdma_destroy_id(rc.cmid);
+       rdma_destroy_id(rc.cmid);
 fail:
        pcs_rpc_reset(ep);
        return;
diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.c b/fs/fuse/kio/pcs/pcs_rdma_io.c
index 62d138c8b611..622ce72c5a85 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_io.c
+++ b/fs/fuse/kio/pcs/pcs_rdma_io.c
@@ -1322,7 +1322,7 @@ struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct 
rdma_cm_id *cmid,
        return NULL;
 }
 
-int pcs_rdma_established(struct pcs_rdmaio *rio)
+int pcs_rdma_setup_rxs(struct pcs_rdmaio *rio)
 {
        struct rio_rx *rx;
 
@@ -1444,20 +1444,35 @@ static void rio_destroy(struct work_struct *work)
 
 static DECLARE_WORK(rio_destroy_work, rio_destroy);
 
+/*
+ * This is only used in case cm error happens during establishing
+ * a connection. We need to destroy the rio immediately such that
+ * the rdma_cm_id can be destroyed immediately afterwards.
+ */
 void pcs_rdma_destroy(struct pcs_rdmaio *rio)
 {
-       struct pcs_netio *netio = &rio->netio;
-       struct pcs_rpc *ep = netio->parent;
+       struct pcs_rpc *ep = rio->netio.parent;
+       int i;
 
        TRACE("rio: 0x%p\n", rio);
 
        BUG_ON(!mutex_is_locked(&ep->mutex));
 
-       netio->eof = NULL;
-       rio_abort(rio, PCS_ERR_NET_ABORT);
+       rio->rio_state = RIO_STATE_ABORTED;
+       rio->rio_error = PCS_ERR_NET_ABORT;
 
-       if (llist_add(&rio->destroy_node, &rio_destroy_list))
-               queue_work(pcs_cleanup_wq, &rio_destroy_work);
+       rdma_disconnect(rio->cmid);
+
+       rdma_destroy_qp(rio->cmid);
+       ib_destroy_cq(rio->cq);
+
+       pcs_rdma_device_destroy(rio->dev);
+       for (i = 0; i < rio->recv_queue_depth; i++)
+               rio_fini_rx(rio->rx_descs + i, rio->cmid->device);
+       kfree(rio->rx_descs);
+
+       pcs_rpc_put(ep);
+       kfree(rio);
 }
 
 void pcs_rdma_ioconn_destruct(struct pcs_ioconn *ioconn)
diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.h b/fs/fuse/kio/pcs/pcs_rdma_io.h
index 18962208e4a2..87cae3764f23 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_io.h
+++ b/fs/fuse/kio/pcs/pcs_rdma_io.h
@@ -113,7 +113,7 @@ struct pcs_rdmaio
 
 struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,
                int queue_depth, struct pcs_rpc *ep);
-int pcs_rdma_established(struct pcs_rdmaio *rio);
+int pcs_rdma_setup_rxs(struct pcs_rdmaio *rio);
 void pcs_rdma_destroy(struct pcs_rdmaio *rio);
 void pcs_rdma_ioconn_destruct(struct pcs_ioconn *ioconn);
 
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to