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@