| From 53a3f777049771496f791504e7dc8ef017cba590 Mon Sep 17 00:00:00 2001 |
| From: Bernard Metzler <bmt@zurich.ibm.com> |
| Date: Tue, 5 Sep 2023 16:58:22 +0200 |
| Subject: RDMA/siw: Fix connection failure handling |
| |
| From: Bernard Metzler <bmt@zurich.ibm.com> |
| |
| commit 53a3f777049771496f791504e7dc8ef017cba590 upstream. |
| |
| In case immediate MPA request processing fails, the newly |
| created endpoint unlinks the listening endpoint and is |
| ready to be dropped. This special case was not handled |
| correctly by the code handling the later TCP socket close, |
| causing a NULL dereference crash in siw_cm_work_handler() |
| when dereferencing a NULL listener. We now also cancel |
| the useless MPA timeout, if immediate MPA request |
| processing fails. |
| |
| This patch furthermore simplifies MPA processing in general: |
| Scheduling a useless TCP socket read in sk_data_ready() upcall |
| is now surpressed, if the socket is already moved out of |
| TCP_ESTABLISHED state. |
| |
| Fixes: 6c52fdc244b5 ("rdma/siw: connection management") |
| Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com> |
| Link: https://lore.kernel.org/r/20230905145822.446263-1-bmt@zurich.ibm.com |
| Signed-off-by: Leon Romanovsky <leon@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/infiniband/sw/siw/siw_cm.c | 16 ++++++++++++---- |
| 1 file changed, 12 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/infiniband/sw/siw/siw_cm.c |
| +++ b/drivers/infiniband/sw/siw/siw_cm.c |
| @@ -973,6 +973,7 @@ static void siw_accept_newconn(struct si |
| siw_cep_put(cep); |
| new_cep->listen_cep = NULL; |
| if (rv) { |
| + siw_cancel_mpatimer(new_cep); |
| siw_cep_set_free(new_cep); |
| goto error; |
| } |
| @@ -1097,9 +1098,12 @@ static void siw_cm_work_handler(struct w |
| /* |
| * Socket close before MPA request received. |
| */ |
| - siw_dbg_cep(cep, "no mpareq: drop listener\n"); |
| - siw_cep_put(cep->listen_cep); |
| - cep->listen_cep = NULL; |
| + if (cep->listen_cep) { |
| + siw_dbg_cep(cep, |
| + "no mpareq: drop listener\n"); |
| + siw_cep_put(cep->listen_cep); |
| + cep->listen_cep = NULL; |
| + } |
| } |
| } |
| release_cep = 1; |
| @@ -1222,7 +1226,11 @@ static void siw_cm_llp_data_ready(struct |
| if (!cep) |
| goto out; |
| |
| - siw_dbg_cep(cep, "state: %d\n", cep->state); |
| + siw_dbg_cep(cep, "cep state: %d, socket state %d\n", |
| + cep->state, sk->sk_state); |
| + |
| + if (sk->sk_state != TCP_ESTABLISHED) |
| + goto out; |
| |
| switch (cep->state) { |
| case SIW_EPSTATE_RDMA_MODE: |