| From foo@baz Sun Jun 17 12:07:34 CEST 2018 |
| From: Zhu Yanjun <yanjun.zhu@oracle.com> |
| Date: Thu, 26 Apr 2018 00:41:10 -0400 |
| Subject: IB/rxe: avoid double kfree_skb |
| |
| From: Zhu Yanjun <yanjun.zhu@oracle.com> |
| |
| [ Upstream commit 9fd4350ba8953804f05215999e11a6cfb7b41f2b ] |
| |
| When skb is sent, it will pass the following functions in soft roce. |
| |
| rxe_send [rdma_rxe] |
| ip_local_out |
| __ip_local_out |
| ip_output |
| ip_finish_output |
| ip_finish_output2 |
| dev_queue_xmit |
| __dev_queue_xmit |
| dev_hard_start_xmit |
| |
| In the above functions, if error occurs in the above functions or |
| iptables rules drop skb after ip_local_out, kfree_skb will be called. |
| So it is not necessary to call kfree_skb in soft roce module again. |
| Or else crash will occur. |
| |
| The steps to reproduce: |
| |
| server client |
| --------- --------- |
| |1.1.1.1|<----rxe-channel--->|1.1.1.2| |
| --------- --------- |
| |
| On server: rping -s -a 1.1.1.1 -v -C 10000 -S 512 |
| On client: rping -c -a 1.1.1.1 -v -C 10000 -S 512 |
| |
| The kernel configs CONFIG_DEBUG_KMEMLEAK and |
| CONFIG_DEBUG_OBJECTS are enabled on both server and client. |
| |
| When rping runs, run the following command in server: |
| |
| iptables -I OUTPUT -p udp --dport 4791 -j DROP |
| |
| Without this patch, crash will occur. |
| |
| CC: Srinivas Eeda <srinivas.eeda@oracle.com> |
| CC: Junxiao Bi <junxiao.bi@oracle.com> |
| Signed-off-by: Zhu Yanjun <yanjun.zhu@oracle.com> |
| Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com> |
| Signed-off-by: Doug Ledford <dledford@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/infiniband/sw/rxe/rxe_req.c | 1 - |
| drivers/infiniband/sw/rxe/rxe_resp.c | 6 +----- |
| 2 files changed, 1 insertion(+), 6 deletions(-) |
| |
| --- a/drivers/infiniband/sw/rxe/rxe_req.c |
| +++ b/drivers/infiniband/sw/rxe/rxe_req.c |
| @@ -728,7 +728,6 @@ next_wqe: |
| rollback_state(wqe, qp, &rollback_wqe, rollback_psn); |
| |
| if (ret == -EAGAIN) { |
| - kfree_skb(skb); |
| rxe_run_task(&qp->req.task, 1); |
| goto exit; |
| } |
| --- a/drivers/infiniband/sw/rxe/rxe_resp.c |
| +++ b/drivers/infiniband/sw/rxe/rxe_resp.c |
| @@ -742,7 +742,6 @@ static enum resp_states read_reply(struc |
| err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb); |
| if (err) { |
| pr_err("Failed sending RDMA reply.\n"); |
| - kfree_skb(skb); |
| return RESPST_ERR_RNR; |
| } |
| |
| @@ -954,10 +953,8 @@ static int send_ack(struct rxe_qp *qp, s |
| } |
| |
| err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb); |
| - if (err) { |
| + if (err) |
| pr_err_ratelimited("Failed sending ack\n"); |
| - kfree_skb(skb); |
| - } |
| |
| err1: |
| return err; |
| @@ -1150,7 +1147,6 @@ static enum resp_states duplicate_reques |
| if (rc) { |
| pr_err("Failed resending result. This flow is not handled - skb ignored\n"); |
| rxe_drop_ref(qp); |
| - kfree_skb(skb_copy); |
| rc = RESPST_CLEANUP; |
| goto out; |
| } |