1 From 308aa2b8f7b7db3332a7d41099fd37851fb793b2 Mon Sep 17 00:00:00 2001
2 From: Steve Wise <swise@opengridcomputing.com>
3 Date: Fri, 31 Aug 2018 07:15:56 -0700
4 Subject: iw_cxgb4: only allow 1 flush on user qps
6 From: Steve Wise <swise@opengridcomputing.com>
8 commit 308aa2b8f7b7db3332a7d41099fd37851fb793b2 upstream.
10 Once the qp has been flushed, it cannot be flushed again. The user qp
11 flush logic wasn't enforcing it however. The bug can cause
12 touch-after-free crashes like:
14 Unable to handle kernel paging request for data at address 0x000001ec
15 Faulting instruction address: 0xc008000016069100
16 Oops: Kernel access of bad area, sig: 11 [#1]
18 NIP [c008000016069100] flush_qp+0x80/0x480 [iw_cxgb4]
19 LR [c00800001606cd6c] c4iw_modify_qp+0x71c/0x11d0 [iw_cxgb4]
21 [c00800001606cd6c] c4iw_modify_qp+0x71c/0x11d0 [iw_cxgb4]
22 [c00800001606e868] c4iw_ib_modify_qp+0x118/0x200 [iw_cxgb4]
23 [c0080000119eae80] ib_security_modify_qp+0xd0/0x3d0 [ib_core]
24 [c0080000119c4e24] ib_modify_qp+0xc4/0x2c0 [ib_core]
25 [c008000011df0284] iwcm_modify_qp_err+0x44/0x70 [iw_cm]
26 [c008000011df0fec] destroy_cm_id+0xcc/0x370 [iw_cm]
27 [c008000011ed4358] rdma_destroy_id+0x3c8/0x520 [rdma_cm]
28 [c0080000134b0540] ucma_close+0x90/0x1b0 [rdma_ucm]
29 [c000000000444da4] __fput+0xe4/0x2f0
31 So fix flush_qp() to only flush the wq once.
33 Cc: stable@vger.kernel.org
34 Signed-off-by: Steve Wise <swise@opengridcomputing.com>
35 Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
36 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40 drivers/infiniband/hw/cxgb4/qp.c | 6 ++++++
41 1 file changed, 6 insertions(+)
43 --- a/drivers/infiniband/hw/cxgb4/qp.c
44 +++ b/drivers/infiniband/hw/cxgb4/qp.c
45 @@ -1258,6 +1258,12 @@ static void flush_qp(struct c4iw_qp *qhp
47 t4_set_wq_in_error(&qhp->wq);
48 if (qhp->ibqp.uobject) {
50 + /* for user qps, qhp->wq.flushed is protected by qhp->mutex */
51 + if (qhp->wq.flushed)
54 + qhp->wq.flushed = 1;
55 t4_set_cq_in_error(&rchp->cq);
56 spin_lock_irqsave(&rchp->comp_handler_lock, flag);
57 (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);