Skip to content

Commit bdf6fa5

Browse files
vyasevichdavem330
authored andcommitted
sctp: handle association restarts when the socket is closed.
Currently association restarts do not take into consideration the state of the socket. When a restart happens, the current assocation simply transitions into established state. This creates a condition where a remote system, through a the restart procedure, may create a local association that is no way reachable by user. The conditions to trigger this are as follows: 1) Remote does not acknoledge some data causing data to remain outstanding. 2) Local application calls close() on the socket. Since data is still outstanding, the association is placed in SHUTDOWN_PENDING state. However, the socket is closed. 3) The remote tries to create a new association, triggering a restart on the local system. The association moves from SHUTDOWN_PENDING to ESTABLISHED. At this point, it is no longer reachable by any socket on the local system. This patch addresses the above situation by moving the newly ESTABLISHED association into SHUTDOWN-SENT state and bundling a SHUTDOWN after the COOKIE-ACK chunk. This way, the restarted associate immidiately enters the shutdown procedure and forces the termination of the unreachable association. Reported-by: David Laight <[email protected]> Signed-off-by: Vlad Yasevich <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f408c3d commit bdf6fa5

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

include/net/sctp/command.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ typedef enum {
115115
* analysis of the state functions, but in reality just taken from
116116
* thin air in the hopes othat we don't trigger a kernel panic.
117117
*/
118-
#define SCTP_MAX_NUM_COMMANDS 14
118+
#define SCTP_MAX_NUM_COMMANDS 20
119119

120120
typedef union {
121121
void *zero_all; /* Set to NULL to clear the entire union */

net/sctp/sm_statefuns.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,9 +1775,22 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
17751775
/* Update the content of current association. */
17761776
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
17771777
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
1778-
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
1779-
SCTP_STATE(SCTP_STATE_ESTABLISHED));
1780-
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1778+
if (sctp_state(asoc, SHUTDOWN_PENDING) &&
1779+
(sctp_sstate(asoc->base.sk, CLOSING) ||
1780+
sock_flag(asoc->base.sk, SOCK_DEAD))) {
1781+
/* if were currently in SHUTDOWN_PENDING, but the socket
1782+
* has been closed by user, don't transition to ESTABLISHED.
1783+
* Instead trigger SHUTDOWN bundled with COOKIE_ACK.
1784+
*/
1785+
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1786+
return sctp_sf_do_9_2_start_shutdown(net, ep, asoc,
1787+
SCTP_ST_CHUNK(0), NULL,
1788+
commands);
1789+
} else {
1790+
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
1791+
SCTP_STATE(SCTP_STATE_ESTABLISHED));
1792+
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
1793+
}
17811794
return SCTP_DISPOSITION_CONSUME;
17821795

17831796
nomem_ev:

0 commit comments

Comments
 (0)