mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 09:02:17 +00:00
RDMA/nes: Fix Xansation test crash on cm_node ref_count
While running a Xansation test, an active side node crashed. The problem started on the passive side, which generated an STtag that was 0. The passive side sent a TERMINATE instead of an MPA REJECT msg. The active side, receives TERMINATE and sends connect_err() and set the cm_node state to CLOSED. The passive side sends FIN + ACK after TERMINATE. Active side ends up in handle_ack_pkt() and send_reset(). send_reset() consumes 1 cm_node's ref_count. Because the cm_node is in CLOSED state, which means that cm_node will be destroyed after completion of the connect_err() indication, CM will crash after send_reset(). Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
parent
f9f3f1e08b
commit
886f98a315
@ -1610,6 +1610,7 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
|||||||
break;
|
break;
|
||||||
case NES_CM_STATE_CLOSED:
|
case NES_CM_STATE_CLOSED:
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
|
add_ref_cm_node(cm_node);
|
||||||
send_reset(cm_node, skb);
|
send_reset(cm_node, skb);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_TSA:
|
case NES_CM_STATE_TSA:
|
||||||
@ -1661,9 +1662,15 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
|||||||
passive_open_err(cm_node, skb, 1);
|
passive_open_err(cm_node, skb, 1);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_LISTENING:
|
case NES_CM_STATE_LISTENING:
|
||||||
|
cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
send_reset(cm_node, skb);
|
||||||
|
break;
|
||||||
case NES_CM_STATE_CLOSED:
|
case NES_CM_STATE_CLOSED:
|
||||||
cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
|
cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
|
add_ref_cm_node(cm_node);
|
||||||
send_reset(cm_node, skb);
|
send_reset(cm_node, skb);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_ESTABLISHED:
|
case NES_CM_STATE_ESTABLISHED:
|
||||||
@ -1732,8 +1739,13 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
|||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_LISTENING:
|
case NES_CM_STATE_LISTENING:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
send_reset(cm_node, skb);
|
||||||
|
break;
|
||||||
case NES_CM_STATE_CLOSED:
|
case NES_CM_STATE_CLOSED:
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
|
add_ref_cm_node(cm_node);
|
||||||
send_reset(cm_node, skb);
|
send_reset(cm_node, skb);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_LAST_ACK:
|
case NES_CM_STATE_LAST_ACK:
|
||||||
@ -2193,8 +2205,11 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
|
|||||||
case NES_CM_STATE_CLOSING:
|
case NES_CM_STATE_CLOSING:
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_MPAREJ_RCVD:
|
|
||||||
case NES_CM_STATE_LISTENING:
|
case NES_CM_STATE_LISTENING:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
send_reset(cm_node, NULL);
|
||||||
|
break;
|
||||||
|
case NES_CM_STATE_MPAREJ_RCVD:
|
||||||
case NES_CM_STATE_UNKNOWN:
|
case NES_CM_STATE_UNKNOWN:
|
||||||
case NES_CM_STATE_INITED:
|
case NES_CM_STATE_INITED:
|
||||||
case NES_CM_STATE_CLOSED:
|
case NES_CM_STATE_CLOSED:
|
||||||
|
Loading…
Reference in New Issue
Block a user