Skip to content

Commit 6c41965

Browse files
Leon Romanovskyjgunthorpe
authored andcommitted
RDMA/mlx5: Don't access ib_qp fields in internal destroy QP path
destroy_qp_common is called for flows where QP is already created by HW. While it is called from IB/core, the ibqp.* fields will be fully initialized, but it is not the case if this function is called during QP creation. Don't rely on ibqp fields as much as possible and initialize send_cq/recv_cq as temporal solution till all drivers will be converted to IB/core QP allocation scheme. refcount_t: underflow; use-after-free. WARNING: CPU: 1 PID: 5372 at lib/refcount.c:28 refcount_warn_saturate+0xfe/0x1a0 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 5372 Comm: syz-executor.2 Not tainted 5.5.0-rc5 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Call Trace: mlx5_core_put_rsc+0x70/0x80 destroy_resource_common+0x8e/0xb0 mlx5_core_destroy_qp+0xaf/0x1d0 mlx5_ib_destroy_qp+0xeb0/0x1460 ib_destroy_qp_user+0x2d5/0x7d0 create_qp+0xed3/0x2130 ib_uverbs_create_qp+0x13e/0x190 ? ib_uverbs_ex_create_qp ib_uverbs_write+0xaa5/0xdf0 __vfs_write+0x7c/0x100 ksys_write+0xc8/0x200 do_syscall_64+0x9c/0x390 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: 08d5397 ("RDMA/mlx5: Copy response to the user in one place") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 4121fb0 commit 6c41965

File tree

1 file changed

+18
-10
lines changed
  • drivers/infiniband/hw/mlx5

1 file changed

+18
-10
lines changed

drivers/infiniband/hw/mlx5/qp.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,18 +2341,18 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
23412341
unsigned long flags;
23422342
int err;
23432343

2344-
if (qp->ibqp.rwq_ind_tbl) {
2344+
if (qp->is_rss) {
23452345
destroy_rss_raw_qp_tir(dev, qp);
23462346
return;
23472347
}
23482348

2349-
base = (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
2349+
base = (qp->type == IB_QPT_RAW_PACKET ||
23502350
qp->flags & IB_QP_CREATE_SOURCE_QPN) ?
2351-
&qp->raw_packet_qp.rq.base :
2352-
&qp->trans_qp.base;
2351+
&qp->raw_packet_qp.rq.base :
2352+
&qp->trans_qp.base;
23532353

23542354
if (qp->state != IB_QPS_RESET) {
2355-
if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET &&
2355+
if (qp->type != IB_QPT_RAW_PACKET &&
23562356
!(qp->flags & IB_QP_CREATE_SOURCE_QPN)) {
23572357
err = mlx5_core_qp_modify(dev, MLX5_CMD_OP_2RST_QP, 0,
23582358
NULL, &base->mqp, NULL);
@@ -2368,8 +2368,8 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
23682368
base->mqp.qpn);
23692369
}
23702370

2371-
get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
2372-
&send_cq, &recv_cq);
2371+
get_cqs(qp->type, qp->ibqp.send_cq, qp->ibqp.recv_cq, &send_cq,
2372+
&recv_cq);
23732373

23742374
spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
23752375
mlx5_ib_lock_cqs(send_cq, recv_cq);
@@ -2391,7 +2391,7 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
23912391
mlx5_ib_unlock_cqs(send_cq, recv_cq);
23922392
spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
23932393

2394-
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET ||
2394+
if (qp->type == IB_QPT_RAW_PACKET ||
23952395
qp->flags & IB_QP_CREATE_SOURCE_QPN) {
23962396
destroy_raw_packet_qp(dev, qp);
23972397
} else {
@@ -3002,10 +3002,18 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
30023002
return &qp->ibqp;
30033003

30043004
destroy_qp:
3005-
if (qp->type == MLX5_IB_QPT_DCT)
3005+
if (qp->type == MLX5_IB_QPT_DCT) {
30063006
mlx5_ib_destroy_dct(qp);
3007-
else
3007+
} else {
3008+
/*
3009+
* The two lines below are temp solution till QP allocation
3010+
* will be moved to be under IB/core responsiblity.
3011+
*/
3012+
qp->ibqp.send_cq = attr->send_cq;
3013+
qp->ibqp.recv_cq = attr->recv_cq;
30083014
destroy_qp_common(dev, qp, udata);
3015+
}
3016+
30093017
qp = NULL;
30103018
free_qp:
30113019
kfree(qp);

0 commit comments

Comments
 (0)