Skip to content

Commit a861dfd

Browse files
RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
jira VULN-38763 cve CVE-2024-42285 commit-author Bart Van Assche <bvanassche@acm.org> commit aee2424 iw_conn_req_handler() associates a new struct rdma_id_private (conn_id) with an existing struct iw_cm_id (cm_id) as follows: conn_id->cm_id.iw = cm_id; cm_id->context = conn_id; cm_id->cm_handler = cma_iw_handler; rdma_destroy_id() frees both the cm_id and the struct rdma_id_private. Make sure that cm_work_handler() does not trigger a use-after-free by only freeing of the struct rdma_id_private after all pending work has finished. Cc: stable@vger.kernel.org Fixes: 59c68ac ("iw_cm: free cm_id resources on the last deref") Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Link: https://lore.kernel.org/r/20240605145117.397751-6-bvanassche@acm.org Signed-off-by: Leon Romanovsky <leon@kernel.org> (cherry picked from commit aee2424) Signed-off-by: Pratham Patel <ppatel@ciq.com>
1 parent 809cb32 commit a861dfd

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

drivers/infiniband/core/iwcm.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,10 @@ EXPORT_SYMBOL(iw_cm_disconnect);
367367
*
368368
* Clean up all resources associated with the connection and release
369369
* the initial reference taken by iw_create_cm_id.
370+
*
371+
* Returns true if and only if the last cm_id_priv reference has been dropped.
370372
*/
371-
static void destroy_cm_id(struct iw_cm_id *cm_id)
373+
static bool destroy_cm_id(struct iw_cm_id *cm_id)
372374
{
373375
struct iwcm_id_private *cm_id_priv;
374376
unsigned long flags;
@@ -436,7 +438,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
436438
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
437439
}
438440

439-
(void)iwcm_deref_id(cm_id_priv);
441+
return iwcm_deref_id(cm_id_priv);
440442
}
441443

442444
/*
@@ -447,7 +449,8 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
447449
*/
448450
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
449451
{
450-
destroy_cm_id(cm_id);
452+
if (!destroy_cm_id(cm_id))
453+
flush_workqueue(iwcm_wq);
451454
}
452455
EXPORT_SYMBOL(iw_destroy_cm_id);
453456

@@ -1024,7 +1027,7 @@ static void cm_work_handler(struct work_struct *_work)
10241027
if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
10251028
ret = process_event(cm_id_priv, &levent);
10261029
if (ret)
1027-
destroy_cm_id(&cm_id_priv->id);
1030+
WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
10281031
} else
10291032
pr_debug("dropping event %d\n", levent.event);
10301033
if (iwcm_deref_id(cm_id_priv))

0 commit comments

Comments
 (0)