tcp: Fix the long standing negative offset panic on output path
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 12 Dec 2011 07:28:04 +0000 (15:28 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 13 Dec 2011 02:17:27 +0000 (10:17 +0800)
commit1ff9b7d322dc5a26f7173aa8c38ecb79da80e419
treecb7626c590f6cb04c2933406bcb4a40c48e20838
parent9b40fbdac1da8214991bb70ab4767862203f2375
tcp: Fix the long standing negative offset panic on output path

This problem shows itself as:
- so_snd is empty
- snd_nxt is less than snd_una, thus stack variable 'off' will be
  negative and stack 'len' variable calculated from 'off' could
  be positive.
- The later on m_copydata() at 'send' label hit the panic, since
  the 'off' passed in is negative

i.e. The panic is triggered by wrong snd_nxt and snd_una

After analysing the coredump, if following things happened, snd_nxt
would be less than snd_una when tcp_output was entered:
1) The SYN was sent to the network.  (snd_nxt=iss+1, snd_una=iss)
2) The retransmit timeout happened for the SYN we had sent, however,
   the MGETHDR on the tcp_output path failed.  (snd_nxt=iss, snd_una=iss)
3) Later on the SYN|ACK for the SYN sent in step 1) came, before
   tcp_output, snd_una=iss+1, while snd_nxt=iss, thus snd_nxt<snd_una

To fix the panic, we just perform all of the state updates as if
MGETHDR was successful in step 2), so snd_nxt could be properly
updated (snd_nxt=iss+1)

Reported-by: pavalos@
sys/netinet/tcp_output.c