| From 17a58b49fd2e6abfe97ed78e02657f94a2365a30 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 16 Jul 2020 22:03:41 +0300 |
| Subject: RDMA/rxe: Prevent access to wr->next ptr afrer wr is posted to send |
| queue |
| |
| From: Mikhail Malygin <m.malygin@yadro.com> |
| |
| [ Upstream commit 5f0b2a6093a4d9aab093964c65083fe801ef1e58 ] |
| |
| rxe_post_send_kernel() iterates over linked list of wr's, until the |
| wr->next ptr is NULL. However if we've got an interrupt after last wr is |
| posted, control may be returned to the code after send completion callback |
| is executed and wr memory is freed. |
| |
| As a result, wr->next pointer may contain incorrect value leading to |
| panic. Store the wr->next on the stack before posting it. |
| |
| Fixes: 8700e3e7c485 ("Soft RoCE driver") |
| Link: https://lore.kernel.org/r/20200716190340.23453-1-m.malygin@yadro.com |
| Signed-off-by: Mikhail Malygin <m.malygin@yadro.com> |
| Signed-off-by: Sergey Kojushev <s.kojushev@yadro.com> |
| Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/infiniband/sw/rxe/rxe_verbs.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c |
| index 9dd4bd7aea92e..2aaa0b592a2d8 100644 |
| --- a/drivers/infiniband/sw/rxe/rxe_verbs.c |
| +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c |
| @@ -683,6 +683,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, |
| unsigned int mask; |
| unsigned int length = 0; |
| int i; |
| + struct ib_send_wr *next; |
| |
| while (wr) { |
| mask = wr_opcode_mask(wr->opcode, qp); |
| @@ -699,6 +700,8 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, |
| break; |
| } |
| |
| + next = wr->next; |
| + |
| length = 0; |
| for (i = 0; i < wr->num_sge; i++) |
| length += wr->sg_list[i].length; |
| @@ -709,7 +712,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, const struct ib_send_wr *wr, |
| *bad_wr = wr; |
| break; |
| } |
| - wr = wr->next; |
| + wr = next; |
| } |
| |
| rxe_run_task(&qp->req.task, 1); |
| -- |
| 2.25.1 |
| |