summaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_timer.c
diff options
context:
space:
mode:
authorJerry Chu <hkchu@google.com>2012-10-22 11:26:36 +0000
committerDavid S. Miller <davem@davemloft.net>2012-10-23 02:42:56 -0400
commit37561f68bd527ec39076e32effdc7b1dcdfb17ea (patch)
tree3b15ff453617ee5ef52e5f7a9885770b4172bc0a /net/ipv4/tcp_timer.c
parent0b63bf1fe6f9ed1ec4148e8896f4522e08476b80 (diff)
downloadlinux-37561f68bd527ec39076e32effdc7b1dcdfb17ea.tar.gz
linux-37561f68bd527ec39076e32effdc7b1dcdfb17ea.tar.bz2
linux-37561f68bd527ec39076e32effdc7b1dcdfb17ea.zip
tcp: Reject invalid ack_seq to Fast Open sockets
A packet with an invalid ack_seq may cause a TCP Fast Open socket to switch to the unexpected TCP_CLOSING state, triggering a BUG_ON kernel panic. When a FIN packet with an invalid ack_seq# arrives at a socket in the TCP_FIN_WAIT1 state, rather than discarding the packet, the current code will accept the FIN, causing state transition to TCP_CLOSING. This may be a small deviation from RFC793, which seems to say that the packet should be dropped. Unfortunately I did not expect this case for Fast Open hence it will trigger a BUG_ON panic. It turns out there is really nothing bad about a TFO socket going into TCP_CLOSING state so I could just remove the BUG_ON statements. But after some thought I think it's better to treat this case like TCP_SYN_RECV and return a RST to the confused peer who caused the unacceptable ack_seq to be generated in the first place. Signed-off-by: H.K. Jerry Chu <hkchu@google.com> Cc: Neal Cardwell <ncardwell@google.com> Cc: Yuchung Cheng <ycheng@google.com> Acked-by: Yuchung Cheng <ycheng@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r--net/ipv4/tcp_timer.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index fc04711e80c8..d47c1b4421a3 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)
return;
}
if (tp->fastopen_rsk) {
- BUG_ON(sk->sk_state != TCP_SYN_RECV &&
- sk->sk_state != TCP_FIN_WAIT1);
+ WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
+ sk->sk_state != TCP_FIN_WAIT1);
tcp_fastopen_synack_timer(sk);
/* Before we receive ACK to our SYN-ACK don't retransmit
* anything else (e.g., data or FIN segments).