mirror of https://gitee.com/openkylin/linux.git
tcp: fix sequence numbers for repaired sockets re-using TIME-WAIT sockets
This patch fixes a bug where the sequence numbers of a socket created using TCP repair functionality are lower than set after connect is called. This occurs when the repair socket overlaps with a TIME-WAIT socket and triggers the re-use code. The amount lower is equal to the number of times that a particular IP/port set is re-used and then put back into TIME-WAIT. Re-using the first time the sequence number is 1 lower, closing that socket and then re-opening (with repair) a new socket with the same addresses/ports puts the sequence number 2 lower than set via setsockopt. The third time is 3 lower, etc. I have not tested what the limit of this acrewal is, if any. The fix is, if a socket is in repair mode, to respect the already set sequence number and timestamp when it would have already re-used the TIME-WAIT socket. Signed-off-by: Stefan Baranoff <sbaranoff@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
83fe6b8709
commit
21684dc46c
|
@ -156,11 +156,24 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|||
*/
|
||||
if (tcptw->tw_ts_recent_stamp &&
|
||||
(!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
|
||||
tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
|
||||
if (tp->write_seq == 0)
|
||||
tp->write_seq = 1;
|
||||
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
|
||||
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
||||
/* In case of repair and re-using TIME-WAIT sockets we still
|
||||
* want to be sure that it is safe as above but honor the
|
||||
* sequence numbers and time stamps set as part of the repair
|
||||
* process.
|
||||
*
|
||||
* Without this check re-using a TIME-WAIT socket with TCP
|
||||
* repair would accumulate a -1 on the repair assigned
|
||||
* sequence number. The first time it is reused the sequence
|
||||
* is -1, the second time -2, etc. This fixes that issue
|
||||
* without appearing to create any others.
|
||||
*/
|
||||
if (likely(!tp->repair)) {
|
||||
tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
|
||||
if (tp->write_seq == 0)
|
||||
tp->write_seq = 1;
|
||||
tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
|
||||
tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
|
||||
}
|
||||
sock_hold(sktw);
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue