Skip to content

Commit ec99fcb

Browse files
committed
RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
jira VULN-38769 cve CVE-2024-42285 commit-author Bart Van Assche <[email protected]> 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: [email protected] Fixes: 59c68ac ("iw_cm: free cm_id resources on the last deref") Reviewed-by: Zhu Yanjun <[email protected]> Tested-by: Shin'ichiro Kawasaki <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> (cherry picked from commit aee2424) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent b5e1afa commit ec99fcb

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
@@ -369,8 +369,10 @@ EXPORT_SYMBOL(iw_cm_disconnect);
369369
*
370370
* Clean up all resources associated with the connection and release
371371
* the initial reference taken by iw_create_cm_id.
372+
*
373+
* Returns true if and only if the last cm_id_priv reference has been dropped.
372374
*/
373-
static void destroy_cm_id(struct iw_cm_id *cm_id)
375+
static bool destroy_cm_id(struct iw_cm_id *cm_id)
374376
{
375377
struct iwcm_id_private *cm_id_priv;
376378
struct ib_qp *qp;
@@ -440,7 +442,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
440442
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
441443
}
442444

443-
(void)iwcm_deref_id(cm_id_priv);
445+
return iwcm_deref_id(cm_id_priv);
444446
}
445447

446448
/*
@@ -451,7 +453,8 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
451453
*/
452454
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
453455
{
454-
destroy_cm_id(cm_id);
456+
if (!destroy_cm_id(cm_id))
457+
flush_workqueue(iwcm_wq);
455458
}
456459
EXPORT_SYMBOL(iw_destroy_cm_id);
457460

@@ -1035,7 +1038,7 @@ static void cm_work_handler(struct work_struct *_work)
10351038
if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
10361039
ret = process_event(cm_id_priv, &levent);
10371040
if (ret)
1038-
destroy_cm_id(&cm_id_priv->id);
1041+
WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
10391042
} else
10401043
pr_debug("dropping event %d\n", levent.event);
10411044
if (iwcm_deref_id(cm_id_priv))

0 commit comments

Comments
 (0)