]> git.proxmox.com Git - mirror_ubuntu-kernels.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)
committerRoxana Nicolescu <roxana.nicolescu@canonical.com>
Fri, 2 Aug 2024 14:27:18 +0000 (16:27 +0200)
BugLink: https://bugs.launchpad.net/bugs/2075154
[ Upstream commit f67ac0061c7614c1548963d3ef1ee1606efd8636 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/infiniband/sw/rxe/rxe_resp.c

index da470a925efc7bbbfc051e4855605ae7f4c31eb3..c02aa27fe5d81747bb099466670b39f6cfccb76d 100644 (file)
@@ -354,6 +354,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;