[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