Message ID | 20240605145117.397751-6-bvanassche@acm.org (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | iWARP Connection Manager patches | expand |
On Wed, Jun 05, 2024 at 08:51:01AM -0600, Bart Van Assche wrote: > 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 This is not right way to mark a patch for stable. I added the following to the commit message and applied the patch: Cc: stable@vger.kernel.org Fixes: 59c68ac31e15 ("iw_cm: free cm_id resources on the last deref") There is no clear Fixes tag which I can use, so I used the latest significant commit that touch that area. Thanks > 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> > --- > drivers/infiniband/core/iwcm.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 4424f430fc08..1a6339f3a63f 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -368,8 +368,10 @@ EXPORT_SYMBOL(iw_cm_disconnect); * * Clean up all resources associated with the connection and release * the initial reference taken by iw_create_cm_id. + * + * Returns true if and only if the last cm_id_priv reference has been dropped. */ -static void destroy_cm_id(struct iw_cm_id *cm_id) +static bool destroy_cm_id(struct iw_cm_id *cm_id) { struct iwcm_id_private *cm_id_priv; struct ib_qp *qp; @@ -439,7 +441,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM); } - (void)iwcm_deref_id(cm_id_priv); + return iwcm_deref_id(cm_id_priv); } /* @@ -450,7 +452,8 @@ static void destroy_cm_id(struct iw_cm_id *cm_id) */ void iw_destroy_cm_id(struct iw_cm_id *cm_id) { - destroy_cm_id(cm_id); + if (!destroy_cm_id(cm_id)) + flush_workqueue(iwcm_wq); } EXPORT_SYMBOL(iw_destroy_cm_id); @@ -1031,7 +1034,7 @@ static void cm_work_handler(struct work_struct *_work) if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) { ret = process_event(cm_id_priv, &levent); if (ret) - destroy_cm_id(&cm_id_priv->id); + WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id)); } else pr_debug("dropping event %d\n", levent.event); if (iwcm_deref_id(cm_id_priv))