aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGuoqing Jiang <guoqing.jiang@linux.dev>2026-08-27 20:55:53 +0800
committerLeon Romanovsky <leon@kernel.org>2026-09-01 03:33:04 -0400
commit32cd87f54dd1070020e664ccb0312a9f0fea79b4 (patch)
treeb029d052ad67f9896848e2501053e7610eff72f4
parentLinux 7.3-rc1 (diff)
RDMA/siw: Clear association under lock if siw_qp_modify fails in siw_accept
We need to clear cep before release state_lock as siw_qp_llp_close and siw_qp_modify->siw_qp_llp_close did. Otherwise if siw_qp_modify() fails in siw_accept(), the QP's state_lock is released before the error path cleanup. A concurrent ibv_modify_qp() transitioning the QP to ERROR can race in this window: siw_accept() ibv_modify_qp(ERROR) ---------------------- ---------------------- siw_qp_modify() fails up_write(&qp->state_lock) down_write(&qp->state_lock) nextstate_from_idle(): if (qp->cep) siw_cep_put(qp->cep) <- frees cep qp->cep = NULL goto error cep->qp = NULL <- UAF Clear qp->cep and drop the association reference taken by siw_cep_get(), all under the write lock held from the initial down_write(&qp->state_lock). Thread B therefore sees qp->cep == NULL, skips its own put, and cannot free the cep before siw_accept() is done with it. Fixes: 6c52fdc244b5 ("rdma/siw: connection management") Reported-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com> Link: https://lore.kernel.org/linux-rdma/d6fbe475-a5c2-f975-99b0-a0bd6b6d10e8@linux.dev/T/#m5876c1ff2de8686a9a1173b8f1aa0ff5363a785c Signed-off-by: Guoqing Jiang <guoqing.jiang@linux.dev> Link: https://patch.msgid.link/20260827125553.12831-1-guoqing.jiang@linux.dev Acked-by: Bernard Metzler <bernard.metzler@linux.dev> Signed-off-by: Leon Romanovsky <leon@kernel.org>
-rw-r--r--drivers/infiniband/sw/siw/siw_cm.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
index 0245b25e7271..ed49818793dd 100644
--- a/drivers/infiniband/sw/siw/siw_cm.c
+++ b/drivers/infiniband/sw/siw/siw_cm.c
@@ -1719,9 +1719,12 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
SIW_QP_ATTR_STATE | SIW_QP_ATTR_LLP_HANDLE |
SIW_QP_ATTR_ORD | SIW_QP_ATTR_IRD |
SIW_QP_ATTR_MPA);
+ if (rv) {
+ qp->cep = NULL;
+ siw_cep_put(cep);
+ goto error_unlock;
+ }
up_write(&qp->state_lock);
- if (rv)
- goto error;
siw_dbg_cep(cep, "[QP %u]: send mpa reply, %d byte pdata\n",
qp_id(qp), params->private_data_len);