IB/hfi1: Add limit test for RC/UC send via loopback [Linux 4.9.156]

This Linux kernel change "IB/hfi1: Add limit test for RC/UC send via loopback" is included in the Linux 4.9.156 release. This change is authored by Mike Marciniszyn <mike.marciniszyn [at] intel.com> on Thu Jan 17 12:42:16 2019 -0800. The commit for this change in Linux stable tree is 2a46975 (patch) which is from upstream commit 09ce351. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 09ce351.

IB/hfi1: Add limit test for RC/UC send via loopback

commit 09ce351dff8e7636af0beb72cd4a86c3904a0500 upstream.

Fix potential memory corruption and panic in loopback for IB_WR_SEND
variants.

The code blindly assumes the posted length will fit in the fetched rwqe,
which is not a valid assumption.

Fix by adding a limit test, and triggering the appropriate send completion
and putting the QP in an error state.  This mimics the handling for
non-loopback QPs.

Fixes: 15703461533a ("IB/{hfi1, qib, rdmavt}: Move ruc_loopback to rdmavt")
Cc: <[email protected]> #v4.20+
Reviewed-by: Michael J. Ruhl <[email protected]>
Signed-off-by: Mike Marciniszyn <[email protected]>
Signed-off-by: Dennis Dalessandro <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Mike Marciniszyn <[email protected]>

There are 14 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/infiniband/hw/hfi1/ruc.c    | 7 ++++++-
 drivers/infiniband/hw/qib/qib_ruc.c | 7 ++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c
index 9f768b4..d151429 100644
--- a/drivers/infiniband/hw/hfi1/ruc.c
+++ b/drivers/infiniband/hw/hfi1/ruc.c
@@ -471,6 +471,8 @@ static void ruc_loopback(struct rvt_qp *sqp)
            goto op_err;
        if (!ret)
            goto rnr_nak;
+       if (wqe->length > qp->r_len)
+           goto inv_err;
        break;

    case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -638,7 +640,10 @@ static void ruc_loopback(struct rvt_qp *sqp)
    goto err;

 inv_err:
-   send_status = IB_WC_REM_INV_REQ_ERR;
+   send_status =
+       sqp->ibqp.qp_type == IB_QPT_RC ?
+           IB_WC_REM_INV_REQ_ERR :
+           IB_WC_SUCCESS;
    wc.status = IB_WC_LOC_QP_OP_ERR;
    goto err;

diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c
index de1bde5..10afde6 100644
--- a/drivers/infiniband/hw/qib/qib_ruc.c
+++ b/drivers/infiniband/hw/qib/qib_ruc.c
@@ -449,6 +449,8 @@ static void qib_ruc_loopback(struct rvt_qp *sqp)
            goto op_err;
        if (!ret)
            goto rnr_nak;
+       if (wqe->length > qp->r_len)
+           goto inv_err;
        break;

    case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -612,7 +614,10 @@ static void qib_ruc_loopback(struct rvt_qp *sqp)
    goto err;

 inv_err:
-   send_status = IB_WC_REM_INV_REQ_ERR;
+   send_status =
+       sqp->ibqp.qp_type == IB_QPT_RC ?
+           IB_WC_REM_INV_REQ_ERR :
+           IB_WC_SUCCESS;
    wc.status = IB_WC_LOC_QP_OP_ERR;
    goto err;

Leave a Reply

Your email address will not be published. Required fields are marked *