[PATCH 3/3] rdma: Get drbd_path->kref when get drbd_path by addr

Philipp Reisner philipp.reisner at linbit.com
Thu Jul 31 14:36:33 CEST 2025


Thanks! Applied.

Best regards,
 Philipp

On Wed, Jul 9, 2025 at 7:22 AM zhengbing.huang
<zhengbing.huang at easystack.cn> 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 <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