Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCTP]: Fix protocol violation when receiving an error lenght INIT-ACK

When receiving an error length INIT-ACK during COOKIE-WAIT,
a 0-vtag ABORT will be responsed. This action violates the
protocol apparently. This patch achieves the following things.
1 If the INIT-ACK contains all the fixed parameters, use init-tag
recorded from INIT-ACK as vtag.
2 If the INIT-ACK doesn't contain all the fixed parameters,
just reflect its vtag.

Signed-off-by: Gui Jianfeng <guijianfeng@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Gui Jianfeng and committed by
David S. Miller
f4ad85ca 72da7b38

+25
+1
include/net/sctp/command.h
··· 104 104 SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ 105 105 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ 106 106 SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ 107 + SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ 107 108 SCTP_CMD_LAST 108 109 } sctp_verb_t; 109 110
+3
net/sctp/outqueue.c
··· 793 793 break; 794 794 795 795 case SCTP_CID_ABORT: 796 + if (sctp_test_T_bit(chunk)) { 797 + packet->vtag = asoc->c.my_vtag; 798 + } 796 799 case SCTP_CID_SACK: 797 800 case SCTP_CID_HEARTBEAT: 798 801 case SCTP_CID_HEARTBEAT_ACK:
+3
net/sctp/sm_sideeffect.c
··· 1536 1536 error = sctp_auth_asoc_init_active_key(asoc, 1537 1537 GFP_ATOMIC); 1538 1538 break; 1539 + case SCTP_CMD_UPDATE_INITTAG: 1540 + asoc->peer.i.init_tag = cmd->obj.u32; 1541 + break; 1539 1542 1540 1543 default: 1541 1544 printk(KERN_WARNING "Impossible command: %u, %p\n",
+18
net/sctp/sm_statefuns.c
··· 4144 4144 goto nomem; 4145 4145 4146 4146 if (asoc) { 4147 + /* Treat INIT-ACK as a special case during COOKIE-WAIT. */ 4148 + if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK && 4149 + !asoc->peer.i.init_tag) { 4150 + sctp_initack_chunk_t *initack; 4151 + 4152 + initack = (sctp_initack_chunk_t *)chunk->chunk_hdr; 4153 + if (!sctp_chunk_length_valid(chunk, 4154 + sizeof(sctp_initack_chunk_t))) 4155 + abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T; 4156 + else { 4157 + unsigned int inittag; 4158 + 4159 + inittag = ntohl(initack->init_hdr.init_tag); 4160 + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG, 4161 + SCTP_U32(inittag)); 4162 + } 4163 + } 4164 + 4147 4165 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 4148 4166 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); 4149 4167