Re: Bug in TCP stack: RST has wrong sequence number?
Re: Bug in TCP stack: RST has wrong sequence number?
- Subject: Re: Bug in TCP stack: RST has wrong sequence number?
- From: Daniel Hartmeier <email@hidden>
- Date: Mon, 19 Feb 2007 22:26:57 +0100
- Resent-date: Tue, 20 Feb 2007 00:43:31 +0100
- Resent-from: email@hidden
- Resent-message-id: <email@hidden>
- Resent-to: email@hidden
On Mon, Feb 19, 2007 at 09:26:04PM +0100, Axel Rau wrote:
> >This is perhaps a corner case in the protocol spec. I'm not sure I
> >buy the conclusion above, but it would be good to hear from the
> >experts.
> >
> >As I read 793, the reset is generated with the current state of the
> >window as the sequence number. From your trace, it looks like the
> >sender (.106) sent data and then immediately reset the connection.
> >The last ack from the receiver (.20) was ...252, so using ...252
> >seems right to me (the sender can't assume that the ...290 segment
> >was/will be received). Judging from the following resets, the
> >stack will use the last-acked sequence number.
> Any comments, Daniel?
RFC 793 seems to imply that reset generation should be using SND.NXT as
sequence number, which isn't the last-acked sequence number, but the
next sequence number to be used for further segments.
But if we look at how Darwin checks th_seq on reset reception, we see
if (thflags & TH_RST) {
if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
(tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
and there's a difference between this and other BSDs, which use
if (tiflags & TH_RST) {
if (th->th_seq != tp->last_ack_sent &&
th->th_seq != tp->rcv_nxt &&
th->th_seq != (tp->rcv_nxt + 1))
goto drop;
This is more strict than the RFC suggests, not allowing the broader
range of "whatever is inside the window", but requiring an exact (or at
most off-by-one) match, to make RST attacks (guessing sequence numbers)
harder.
But it also allows last_ack_sent, which at least acknowledges that some
stacks use the last-acked sequence number in reset generation.
What I don't understand is how Darwin's tcp_output() is intentionally
using the last-acked value for reset generation. Looking at
tcp_output.c, it does
if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
th->th_seq = htonl(tp->snd_nxt);
else
th->th_seq = htonl(tp->snd_max);
And snd_nxt/_max should not be tracking last-acked, but the right edge,
i.e. tcp_input() is not updating snd_nxt/_max based on ACKs, but only
tcp_output() is updating it, based on segments sent (even if not
acknowledged). In our example, the right edge should definitely be ...290,
no?
Daniel
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden