mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
tcp: improve SEG.SEQ validation for RST segments
A RST segment can be sent in response to (a) received segment or (b) by the upper layer protocol. The SEG.SEQ validation consists of two checks: (1) the in-window check of SEG.SEQ and (2) the exact match check of SEG.SEQ. For the in-window check (1), the left edge of the window needs to be based on tp->last_ack_sent to cover the delayed ACK case, whereas the right edge needs to be based on tp->rcv_nxt + tp->rcv_wnd. This both assumes that tp->rcv_wnd is not zero. For the special case of tp->rcv_wnd being zero, add checks against tp->last_ack_sent for (a) and on tp->rcv_nxt for (b). This applies to all TCP stacks. When the exact match (2) of SEG.SEQ is performed, it should be based on tp->last_ack_sent for (a) and on tp->rcv_nxt for (b). To cover both, check for both. Add this only to the base stack, since the RACK and BBR stacks already do this. PR: 296594 Reviewed by: rscheff MFC after: 3 days MFC to: stable/14 MFC to: stable/15 Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D58594
This commit is contained in:
1 parent
a108ee9138
commit
c9df1a6cf9
2 files changed
+26
-14
No files matched your search
+12
-6
@@ -2125,20 +2125,26 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
||||
* - RST drops connection only if SEG.SEQ == RCV.NXT.
|
||||
* - If RST is in window, we send challenge ACK.
|
||||
*
|
||||
* Note: to take into account delayed ACKs, we should
|
||||
* test against last_ack_sent instead of rcv_nxt.
|
||||
* Note 1: to take into account delayed ACKs, we should
|
||||
* test against last_ack_sent in addition to rcv_nxt.
|
||||
* Note 2: we handle special case of closed window, not
|
||||
* covered by the RFC.
|
||||
* Note 3 (XXXMT): check against rcv_adv instead of
|
||||
* tp->rcv_nxt + tp->rcv_wnd.
|
||||
*/
|
||||
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)) {
|
||||
if ((tp->rcv_wnd > 0 &&
|
||||
SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
|
||||
SEQ_LT(th->th_seq, tp->rcv_nxt + tp->rcv_wnd)) ||
|
||||
(tp->rcv_wnd == 0 &&
|
||||
(tp->last_ack_sent == th->th_seq ||
|
||||
tp->rcv_nxt == th->th_seq))) {
|
||||
KASSERT(tp->t_state != TCPS_SYN_SENT,
|
||||
("%s: TH_RST for TCPS_SYN_SENT th %p tp %p",
|
||||
__func__, th, tp));
|
||||
|
||||
if (V_tcp_insecure_rst ||
|
||||
tp->last_ack_sent == th->th_seq) {
|
||||
tp->last_ack_sent == th->th_seq ||
|
||||
tp->rcv_nxt == th->th_seq) {
|
||||
TCPSTAT_INC(tcps_drops);
|
||||
/* Drop the connection. */
|
||||
switch (tp->t_state) {
|
||||
|
||||
@@ -697,18 +697,24 @@ ctf_process_rst(struct mbuf *m, struct tcphdr *th, struct socket *so,
|
||||
/*
|
||||
* RFC5961 Section 3.2
|
||||
*
|
||||
* - RST drops connection only if SEG.SEQ == RCV.NXT. - If RST is in
|
||||
* window, we send challenge ACK.
|
||||
* - RST drops connection only if SEG.SEQ == RCV.NXT.
|
||||
* - If RST is in window, we send challenge ACK.
|
||||
*
|
||||
* Note: to take into account delayed ACKs, we should test against
|
||||
* last_ack_sent instead of rcv_nxt. Note 2: we handle special case
|
||||
* of closed window, not covered by the RFC.
|
||||
* Note 1: to take into account delayed ACKs, we should
|
||||
* test against last_ack_sent in addition to rcv_nxt.
|
||||
* Note 2: we handle special case of closed window, not
|
||||
* covered by the RFC.
|
||||
* Note 3 (XXXMT): check against rcv_adv instead of
|
||||
* tp->rcv_nxt + tp->rcv_wnd.
|
||||
*/
|
||||
int dropped = 0;
|
||||
|
||||
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)) {
|
||||
if ((tp->rcv_wnd > 0 &&
|
||||
SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
|
||||
SEQ_LT(th->th_seq, tp->rcv_nxt + tp->rcv_wnd)) ||
|
||||
(tp->rcv_wnd == 0 &&
|
||||
(tp->last_ack_sent == th->th_seq ||
|
||||
tp->rcv_nxt == th->th_seq))) {
|
||||
KASSERT(tp->t_state != TCPS_SYN_SENT,
|
||||
("%s: TH_RST for TCPS_SYN_SENT th %p tp %p",
|
||||
__func__, th, tp));
|
||||
|
||||
Reference in new issue
Block a user