[Devel] [PATCH RHEL9] fs/fuse kio: destroy rdma_cm_id immediately in case cm fails during connection establishment
Kui Liu
Kui.Liu at acronis.com
Tue Jan 2 11:58:36 MSK 2024
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.
Fixes
https://pmc.acronis.work/browse/VSTOR-79838
Signed-off-by: Liu Kui <kui.liu at acronis.com>
---
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);
--
2.32.0 (Apple Git-132)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/devel/attachments/20240102/86460d04/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-fs-fuse-kio-destroy-rdma_cm_id-immediately-in-case-c.patch
Type: application/octet-stream
Size: 4674 bytes
Desc: 0001-fs-fuse-kio-destroy-rdma_cm_id-immediately-in-case-c.patch
URL: <http://lists.openvz.org/pipermail/devel/attachments/20240102/86460d04/attachment-0001.obj>
More information about the Devel
mailing list