Skip to content

Commit 5ff31df

Browse files
Bob Pearsonjgunthorpe
authored andcommitted
Subject: RDMA/rxe: Handle zero length rdma
Currently the rxe driver does not handle all cases of zero length rdma operations correctly. The client does not have to provide an rkey for zero length RDMA read or write operations so the rkey provided may be invalid and should not be used to lookup an mr. This patch corrects the driver to ignore the provided rkey if the reth length is zero for read or write operations and make sure to set the mr to NULL. In read_reply() if length is zero rxe_recheck_mr() is not called. Warnings are added in the routines in rxe_mr.c to catch NULL MRs when the length is non-zero. Fixes: 8700e3e ("Soft RoCE driver") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bob Pearson <[email protected]> Reviewed-by: Daisuke Matsuda <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 4ca446b commit 5ff31df

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

drivers/infiniband/sw/rxe/rxe_mr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,9 @@ int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr,
314314
if (length == 0)
315315
return 0;
316316

317+
if (WARN_ON(!mr))
318+
return -EINVAL;
319+
317320
if (mr->ibmr.type == IB_MR_TYPE_DMA) {
318321
rxe_mr_copy_dma(mr, iova, addr, length, dir);
319322
return 0;
@@ -432,6 +435,10 @@ int rxe_flush_pmem_iova(struct rxe_mr *mr, u64 iova, unsigned int length)
432435
int err;
433436
u8 *va;
434437

438+
/* mr must be valid even if length is zero */
439+
if (WARN_ON(!mr))
440+
return -EINVAL;
441+
435442
if (length == 0)
436443
return 0;
437444

drivers/infiniband/sw/rxe/rxe_resp.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,23 @@ static enum resp_states rxe_resp_check_length(struct rxe_qp *qp,
420420
return RESPST_CHK_RKEY;
421421
}
422422

423+
/* if the reth length field is zero we can assume nothing
424+
* about the rkey value and should not validate or use it.
425+
* Instead set qp->resp.rkey to 0 which is an invalid rkey
426+
* value since the minimum index part is 1.
427+
*/
423428
static void qp_resp_from_reth(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
424429
{
430+
unsigned int length = reth_len(pkt);
431+
425432
qp->resp.va = reth_va(pkt);
426433
qp->resp.offset = 0;
427-
qp->resp.rkey = reth_rkey(pkt);
428-
qp->resp.resid = reth_len(pkt);
429-
qp->resp.length = reth_len(pkt);
434+
qp->resp.resid = length;
435+
qp->resp.length = length;
436+
if (pkt->mask & RXE_READ_OR_WRITE_MASK && length == 0)
437+
qp->resp.rkey = 0;
438+
else
439+
qp->resp.rkey = reth_rkey(pkt);
430440
}
431441

432442
static void qp_resp_from_atmeth(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
@@ -437,6 +447,10 @@ static void qp_resp_from_atmeth(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
437447
qp->resp.resid = sizeof(u64);
438448
}
439449

450+
/* resolve the packet rkey to qp->resp.mr or set qp->resp.mr to NULL
451+
* if an invalid rkey is received or the rdma length is zero. For middle
452+
* or last packets use the stored value of mr.
453+
*/
440454
static enum resp_states check_rkey(struct rxe_qp *qp,
441455
struct rxe_pkt_info *pkt)
442456
{
@@ -473,10 +487,12 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
473487
return RESPST_EXECUTE;
474488
}
475489

476-
/* A zero-byte op is not required to set an addr or rkey. See C9-88 */
490+
/* A zero-byte read or write op is not required to
491+
* set an addr or rkey. See C9-88
492+
*/
477493
if ((pkt->mask & RXE_READ_OR_WRITE_MASK) &&
478-
(pkt->mask & RXE_RETH_MASK) &&
479-
reth_len(pkt) == 0) {
494+
(pkt->mask & RXE_RETH_MASK) && reth_len(pkt) == 0) {
495+
qp->resp.mr = NULL;
480496
return RESPST_EXECUTE;
481497
}
482498

@@ -555,6 +571,7 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
555571
return RESPST_EXECUTE;
556572

557573
err:
574+
qp->resp.mr = NULL;
558575
if (mr)
559576
rxe_put(mr);
560577
if (mw)
@@ -885,7 +902,11 @@ static enum resp_states read_reply(struct rxe_qp *qp,
885902
}
886903

887904
if (res->state == rdatm_res_state_new) {
888-
if (!res->replay) {
905+
if (!res->replay || qp->resp.length == 0) {
906+
/* if length == 0 mr will be NULL (is ok)
907+
* otherwise qp->resp.mr holds a ref on mr
908+
* which we transfer to mr and drop below.
909+
*/
889910
mr = qp->resp.mr;
890911
qp->resp.mr = NULL;
891912
} else {
@@ -899,6 +920,10 @@ static enum resp_states read_reply(struct rxe_qp *qp,
899920
else
900921
opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST;
901922
} else {
923+
/* re-lookup mr from rkey on all later packets.
924+
* length will be non-zero. This can fail if someone
925+
* modifies or destroys the mr since the first packet.
926+
*/
902927
mr = rxe_recheck_mr(qp, res->read.rkey);
903928
if (!mr)
904929
return RESPST_ERR_RKEY_VIOLATION;
@@ -916,18 +941,16 @@ static enum resp_states read_reply(struct rxe_qp *qp,
916941
skb = prepare_ack_packet(qp, &ack_pkt, opcode, payload,
917942
res->cur_psn, AETH_ACK_UNLIMITED);
918943
if (!skb) {
919-
if (mr)
920-
rxe_put(mr);
921-
return RESPST_ERR_RNR;
944+
state = RESPST_ERR_RNR;
945+
goto err_out;
922946
}
923947

924948
err = rxe_mr_copy(mr, res->read.va, payload_addr(&ack_pkt),
925949
payload, RXE_FROM_MR_OBJ);
926-
if (mr)
927-
rxe_put(mr);
928950
if (err) {
929951
kfree_skb(skb);
930-
return RESPST_ERR_RKEY_VIOLATION;
952+
state = RESPST_ERR_RKEY_VIOLATION;
953+
goto err_out;
931954
}
932955

933956
if (bth_pad(&ack_pkt)) {
@@ -936,9 +959,12 @@ static enum resp_states read_reply(struct rxe_qp *qp,
936959
memset(pad, 0, bth_pad(&ack_pkt));
937960
}
938961

962+
/* rxe_xmit_packet always consumes the skb */
939963
err = rxe_xmit_packet(qp, &ack_pkt, skb);
940-
if (err)
941-
return RESPST_ERR_RNR;
964+
if (err) {
965+
state = RESPST_ERR_RNR;
966+
goto err_out;
967+
}
942968

943969
res->read.va += payload;
944970
res->read.resid -= payload;
@@ -955,6 +981,9 @@ static enum resp_states read_reply(struct rxe_qp *qp,
955981
state = RESPST_CLEANUP;
956982
}
957983

984+
err_out:
985+
if (mr)
986+
rxe_put(mr);
958987
return state;
959988
}
960989

0 commit comments

Comments
 (0)