diff options
author | Stefan Baranoff <sbaranoff@gmail.com> | 2018-07-10 17:25:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-07-12 17:33:45 -0400 |
commit | 21684dc46c598e477707487c009f9773f7c0382d (patch) | |
tree | e32dc7d79947a09fc058069de742ea476db4cc83 /net/ipv4/tcp_ipv4.c | |
parent | 83fe6b8709f65bc505b10235bd82ece12c4c5099 (diff) |
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>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index bea17f1e8302..3b2711e33e4c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -156,11 +156,24 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) | |||
156 | */ | 156 | */ |
157 | if (tcptw->tw_ts_recent_stamp && | 157 | if (tcptw->tw_ts_recent_stamp && |
158 | (!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) { | 158 | (!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) { |
159 | tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; | 159 | /* In case of repair and re-using TIME-WAIT sockets we still |
160 | if (tp->write_seq == 0) | 160 | * want to be sure that it is safe as above but honor the |
161 | tp->write_seq = 1; | 161 | * sequence numbers and time stamps set as part of the repair |
162 | tp->rx_opt.ts_recent = tcptw->tw_ts_recent; | 162 | * process. |
163 | tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; | 163 | * |
164 | * Without this check re-using a TIME-WAIT socket with TCP | ||
165 | * repair would accumulate a -1 on the repair assigned | ||
166 | * sequence number. The first time it is reused the sequence | ||
167 | * is -1, the second time -2, etc. This fixes that issue | ||
168 | * without appearing to create any others. | ||
169 | */ | ||
170 | if (likely(!tp->repair)) { | ||
171 | tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; | ||
172 | if (tp->write_seq == 0) | ||
173 | tp->write_seq = 1; | ||
174 | tp->rx_opt.ts_recent = tcptw->tw_ts_recent; | ||
175 | tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; | ||
176 | } | ||
164 | sock_hold(sktw); | 177 | sock_hold(sktw); |
165 | return 1; | 178 | return 1; |
166 | } | 179 | } |