]> git.dujemihanovic.xyz Git - linux.git/commitdiff
RDMA/rxe: Fix responder length checking for UD request packets
authorHonggang LI <honggangli@163.com>
Thu, 23 May 2024 09:46:17 +0000 (17:46 +0800)
committerLeon Romanovsky <leon@kernel.org>
Sun, 9 Jun 2024 08:51:32 +0000 (11:51 +0300)
According to the IBA specification:
If a UD request packet is detected with an invalid length, the request
shall be an invalid request and it shall be silently dropped by
the responder. The responder then waits for a new request packet.

commit 689c5421bfe0 ("RDMA/rxe: Fix incorrect responder length checking")
defers responder length check for UD QPs in function `copy_data`.
But it introduces a regression issue for UD QPs.

When the packet size is too large to fit in the receive buffer.
`copy_data` will return error code -EINVAL. Then `send_data_in`
will return RESPST_ERR_MALFORMED_WQE. UD QP will transfer into
ERROR state.

Fixes: 689c5421bfe0 ("RDMA/rxe: Fix incorrect responder length checking")
Signed-off-by: Honggang LI <honggangli@163.com>
Link: https://lore.kernel.org/r/20240523094617.141148-1-honggangli@163.com
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/sw/rxe/rxe_resp.c

index c6a7fa3054fada989014872d416a0c22e2314d2c..6596a85723c9a515667f987758ef00fceb8d8298 100644 (file)
@@ -344,6 +344,19 @@ static enum resp_states rxe_resp_check_length(struct rxe_qp *qp,
         * receive buffer later. For rmda operations additional
         * length checks are performed in check_rkey.
         */
+       if ((qp_type(qp) == IB_QPT_GSI) || (qp_type(qp) == IB_QPT_UD)) {
+               unsigned int payload = payload_size(pkt);
+               unsigned int recv_buffer_len = 0;
+               int i;
+
+               for (i = 0; i < qp->resp.wqe->dma.num_sge; i++)
+                       recv_buffer_len += qp->resp.wqe->dma.sge[i].length;
+               if (payload + 40 > recv_buffer_len) {
+                       rxe_dbg_qp(qp, "The receive buffer is too small for this UD packet.\n");
+                       return RESPST_ERR_LENGTH;
+               }
+       }
+
        if (pkt->mask & RXE_PAYLOAD_MASK && ((qp_type(qp) == IB_QPT_RC) ||
                                             (qp_type(qp) == IB_QPT_UC))) {
                unsigned int mtu = qp->mtu;