Re: [PATCH 3/3] rdma: Get drbd_path->kref when get drbd_path by addr
Philipp Reisner <[email protected]> Thu, 31 Jul 2025 14:36:33 +0200
| Newsgroups | dev.linux.lists.drbd-dev |
|---|---|
| Message-ID | <CADGDV=WFc4H5eG0rVcp+Ms6XiosSbomVg6CWBvetWi0T=Bt_LA@mail.gmail.com> |
Thanks! Applied. Best regards, Philipp On Wed, Jul 9, 2025 at 7:22 AM zhengbing.huang <[email protected]> wrote: > > 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 <[email protected]> > --- > 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 >