[PATCH 3/3] rdma: Get drbd_path->kref when get drbd_path by addr
zhengbing.huang
zhengbing.huang at easystack.cn
Wed Jul 9 04:55:52 CEST 2025
In the dtr_cma_accept() function, after obtain the drbd_path
through peer_addr, without take a reference,
the drbd_path may be released concurrently, leade to a use-after-free.
So when we obtain drbd_path, we add a reference count.
Signed-off-by: zhengbing.huang <zhengbing.huang at easystack.cn>
---
drbd/drbd_transport_rdma.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drbd/drbd_transport_rdma.c b/drbd/drbd_transport_rdma.c
index 442dd8e89..68c668f7f 100644
--- a/drbd/drbd_transport_rdma.c
+++ b/drbd/drbd_transport_rdma.c
@@ -969,6 +969,8 @@ static int dtr_cma_accept(struct dtr_listener *listener, struct rdma_cm_id *new_
spin_lock(&listener->listener.waiters_lock);
drbd_path = drbd_find_path_by_addr(&listener->listener, peer_addr);
+ if (drbd_path)
+ kref_get(&drbd_path->kref);
spin_unlock(&listener->listener.waiters_lock);
if (!drbd_path) {
@@ -997,16 +999,13 @@ static int dtr_cma_accept(struct dtr_listener *listener, struct rdma_cm_id *new_
path = container_of(drbd_path, struct dtr_path, path);
cs = &path->cs;
- if (atomic_read(&cs->passive_state) < PCS_CONNECTING) {
- rdma_reject(new_cm_id, NULL, 0, IB_CM_REJ_CONSUMER_DEFINED);
- return -EAGAIN;
- }
+ if (atomic_read(&cs->passive_state) < PCS_CONNECTING)
+ goto reject;
cm = dtr_alloc_cm(path);
if (!cm) {
pr_err("rejecting connecting since -ENOMEM for cm\n");
- rdma_reject(new_cm_id, NULL, 0, IB_CM_REJ_CONSUMER_DEFINED);
- return -EAGAIN;
+ goto reject;
}
cm->state = DSM_CONNECT_REQ;
@@ -1024,17 +1023,21 @@ static int dtr_cma_accept(struct dtr_listener *listener, struct rdma_cm_id *new_
/* Gifting the initial kref to the path->cm pointer */
err = dtr_path_prepare(path, cm, false);
if (err) {
- rdma_reject(new_cm_id, NULL, 0, IB_CM_REJ_CONSUMER_DEFINED);
/* Returning the cm via ret_cm and an error causes the caller to put one ref */
-
- return -EAGAIN;
+ goto reject;
}
+ kref_put(&drbd_path->kref, drbd_destroy_path);
err = rdma_accept(new_cm_id, &dtr_conn_param);
if (err)
kref_put(&cm->kref, dtr_destroy_cm);
return err;
+
+reject:
+ rdma_reject(new_cm_id, NULL, 0, IB_CM_REJ_CONSUMER_DEFINED);
+ kref_put(&drbd_path->kref, drbd_destroy_path);
+ return -EAGAIN;
}
static int dtr_start_try_connect(struct dtr_connect_state *cs)
--
2.43.0
More information about the drbd-dev
mailing list