Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH for-next] RDMA/rxe: Handle zero length cases correctly
@ 2023-01-19 19:06 Bob Pearson
  2023-01-20  1:38 ` Zhu Yanjun
  0 siblings, 1 reply; 7+ messages in thread
From: Bob Pearson @ 2023-01-19 19:06 UTC (permalink / raw)
  To: jgg, zyjzyj2000, leonro, linux-rdma; +Cc: Bob Pearson

Currently the rxe driver, in rare situations, can respond incorrectly
to zero length operations which are retried. The client does not
have to provide an rkey for zero length RDMA operations so the rkey
may be invalid. The driver saves this rkey in the responder resources
to replay the rdma operation if a retry is required so the second pass
will use this (potentially) invalid rkey which may result in memory
faults.

This patch corrects the driver to ignore the provided rkey if the
reth length is zero and make sure to set the mr to NULL. In read_reply()
if the length is zero the MR is set to NULL. Warnings are added in
the routines in rxe_mr.c to catch NULL MRs when the length is non-zero.

Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
---
 drivers/infiniband/sw/rxe/rxe_mr.c   |  9 +++++++
 drivers/infiniband/sw/rxe/rxe_resp.c | 36 +++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index 072eac4b65d2..134a74f315c2 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -267,6 +267,9 @@ void *iova_to_vaddr(struct rxe_mr *mr, u64 iova, int length)
 	int m, n;
 	void *addr;
 
+	if (WARN_ON(!mr))
+		return NULL;
+
 	if (mr->state != RXE_MR_STATE_VALID) {
 		rxe_dbg_mr(mr, "Not in valid state\n");
 		addr = NULL;
@@ -305,6 +308,9 @@ int rxe_flush_pmem_iova(struct rxe_mr *mr, u64 iova, int length)
 	if (length == 0)
 		return 0;
 
+	if (WARN_ON(!mr))
+		return -EINVAL;
+
 	if (mr->ibmr.type == IB_MR_TYPE_DMA)
 		return -EFAULT;
 
@@ -349,6 +355,9 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length,
 	if (length == 0)
 		return 0;
 
+	if (WARN_ON(!mr))
+		return -EINVAL;
+
 	if (mr->ibmr.type == IB_MR_TYPE_DMA) {
 		u8 *src, *dest;
 
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
index c74972244f08..a528dc25d389 100644
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -457,13 +457,23 @@ static enum resp_states rxe_resp_check_length(struct rxe_qp *qp,
 	return RESPST_CHK_RKEY;
 }
 
+/* if the reth length field is zero we can assume nothing
+ * about the rkey value and should not validate or use it.
+ * Instead set qp->resp.rkey to 0 which is an invalid rkey
+ * value since the minimum index part is 1.
+ */
 static void qp_resp_from_reth(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
 {
+	unsigned int length = reth_len(pkt);
+
 	qp->resp.va = reth_va(pkt);
 	qp->resp.offset = 0;
-	qp->resp.rkey = reth_rkey(pkt);
-	qp->resp.resid = reth_len(pkt);
-	qp->resp.length = reth_len(pkt);
+	qp->resp.resid = length;
+	qp->resp.length = length;
+	if (length)
+		qp->resp.rkey = reth_rkey(pkt);
+	else
+		qp->resp.rkey = 0;
 }
 
 static void qp_resp_from_atmeth(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
@@ -512,8 +522,8 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
 
 	/* A zero-byte op is not required to set an addr or rkey. See C9-88 */
 	if ((pkt->mask & RXE_READ_OR_WRITE_MASK) &&
-	    (pkt->mask & RXE_RETH_MASK) &&
-	    reth_len(pkt) == 0) {
+	    (pkt->mask & RXE_RETH_MASK) && reth_len(pkt) == 0) {
+		qp->resp.mr = NULL;
 		return RESPST_EXECUTE;
 	}
 
@@ -592,6 +602,7 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
 	return RESPST_EXECUTE;
 
 err:
+	qp->resp.mr = NULL;
 	if (mr)
 		rxe_put(mr);
 	if (mw)
@@ -966,7 +977,10 @@ static enum resp_states read_reply(struct rxe_qp *qp,
 	}
 
 	if (res->state == rdatm_res_state_new) {
-		if (!res->replay) {
+		if (qp->resp.length == 0) {
+			mr = NULL;
+			qp->resp.mr = NULL;
+		} else if (!res->replay) {
 			mr = qp->resp.mr;
 			qp->resp.mr = NULL;
 		} else {
@@ -980,9 +994,13 @@ static enum resp_states read_reply(struct rxe_qp *qp,
 		else
 			opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST;
 	} else {
-		mr = rxe_recheck_mr(qp, res->read.rkey);
-		if (!mr)
-			return RESPST_ERR_RKEY_VIOLATION;
+		if (qp->resp.length == 0) {
+			mr = NULL;
+		} else {
+			mr = rxe_recheck_mr(qp, res->read.rkey);
+			if (!mr)
+				return RESPST_ERR_RKEY_VIOLATION;
+		}
 
 		if (res->read.resid > mtu)
 			opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE;
-- 
2.37.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-01-27 16:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-19 19:06 [PATCH for-next] RDMA/rxe: Handle zero length cases correctly Bob Pearson
2023-01-20  1:38 ` Zhu Yanjun
2023-01-20  4:27   ` Bob Pearson
2023-01-20  6:04     ` Zhu Yanjun
2023-01-23 10:20       ` Daisuke Matsuda (Fujitsu)
2023-01-24 22:03         ` Bob Pearson
2023-01-27 16:24           ` Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox