Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-6]: src/sys/netinet Pullup patch (requested by itojun in ticket...



details:   https://anonhg.NetBSD.org/src/rev/1bb899db9408
branches:  netbsd-1-6
changeset: 531315:1bb899db9408
user:      jmc <jmc%NetBSD.org@localhost>
date:      Tue Apr 20 20:26:43 2004 +0000

description:
Pullup patch (requested by itojun in ticket #1680)

If a segment is received with RST set and the segment is completely to the
left of the receive window, ignore it.  Add some additional comments to
the code that deals with received segemnts that are completely to the right
of the receive window.  If an invalid SYN is received, force an ACK and
drop it; if the other side really sent the SYN; it'll respond with a reset.
Respond to RST by ACK, as suggested in NISCC recommendation.
Rate-limit ACKs against RSTs and SYNs.
If SYN is coming and RCV.NXT == SEG.SEQ, then ACK with value - 1.

diffstat:

 sys/netinet/tcp_input.c |  114 ++++++++++++++++++++++++++++++++++-------------
 sys/netinet/tcp_subr.c  |    5 +-
 sys/netinet/tcp_var.h   |   12 ++++-
 3 files changed, 94 insertions(+), 37 deletions(-)

diffs (256 lines):

diff -r 32235e9509da -r 1bb899db9408 sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c   Tue Apr 20 06:22:39 2004 +0000
+++ b/sys/netinet/tcp_input.c   Tue Apr 20 20:26:43 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.141.4.7 2003/10/22 06:05:47 jmc Exp $  */
+/*     $NetBSD: tcp_input.c,v 1.141.4.8 2004/04/20 20:26:52 jmc Exp $  */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -152,7 +152,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.141.4.7 2003/10/22 06:05:47 jmc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.141.4.8 2004/04/20 20:26:52 jmc Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -228,6 +228,8 @@
 
 static int tcp_rst_ppslim_count = 0;
 static struct timeval tcp_rst_ppslim_last;
+static int tcp_ackdrop_ppslim_count = 0;
+static struct timeval tcp_ackdrop_ppslim_last;
 
 #define TCP_PAWS_IDLE  (24 * 24 * 60 * 60 * PR_SLOWHZ)
 
@@ -1714,11 +1716,13 @@
                if (todrop > tlen ||
                    (todrop == tlen && (tiflags & TH_FIN) == 0)) {
                        /*
-                        * Any valid FIN must be to the left of the window.
-                        * At this point the FIN must be a duplicate or
-                        * out of sequence; drop it.
+                        * Any valid FIN or RST must be to the left of the
+                        * window.  At this point the FIN or RST must be a
+                        * duplicate or out of sequence; drop it.
                         */
-                       tiflags &= ~TH_FIN;
+                       if (tiflags & TH_RST)
+                               goto drop;
+                       tiflags &= ~(TH_FIN|TH_RST);
                        /*
                         * Send an ACK to resynchronize and drop any data.
                         * But keep on processing for RST or ACK.
@@ -1761,6 +1765,12 @@
        if (todrop > 0) {
                tcpstat.tcps_rcvpackafterwin++;
                if (todrop >= tlen) {
+                       /*
+                        * The segment actually starts after the window.
+                        * th->th_seq + tlen - tp->rcv_nxt - tp->rcv_wnd >= tlen
+                        * th->th_seq - tp->rcv_nxt - tp->rcv_wnd >= 0
+                        * th->th_seq >= tp->rcv_nxt + tp->rcv_wnd
+                        */
                        tcpstat.tcps_rcvbyteafterwin += tlen;
                        /*
                         * If a new connection request is received
@@ -1788,7 +1798,7 @@
                         * window edge, and have to drop data and PUSH from
                         * incoming segments.  Continue processing, but
                         * remember to ack.  Otherwise, drop segment
-                        * and ack.
+                        * and (if not RST) ack.
                         */
                        if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) {
                                tp->t_flags |= TF_ACKNOW;
@@ -1824,37 +1834,52 @@
         *    CLOSING, LAST_ACK, TIME_WAIT STATES
         *      Close the tcb.
         */
-       if (tiflags&TH_RST) switch (tp->t_state) {
-
-       case TCPS_SYN_RECEIVED:
-               so->so_error = ECONNREFUSED;
-               goto close;
-
-       case TCPS_ESTABLISHED:
-       case TCPS_FIN_WAIT_1:
-       case TCPS_FIN_WAIT_2:
-       case TCPS_CLOSE_WAIT:
-               so->so_error = ECONNRESET;
-       close:
-               tp->t_state = TCPS_CLOSED;
-               tcpstat.tcps_drops++;
-               tp = tcp_close(tp);
-               goto drop;
-
-       case TCPS_CLOSING:
-       case TCPS_LAST_ACK:
-       case TCPS_TIME_WAIT:
-               tp = tcp_close(tp);
-               goto drop;
+       if (tiflags & TH_RST) {
+               if (th->th_seq != tp->last_ack_sent)
+                       goto dropafterack_ratelim;
+
+               switch (tp->t_state) {
+               case TCPS_SYN_RECEIVED:
+                       so->so_error = ECONNREFUSED;
+                       goto close;
+
+               case TCPS_ESTABLISHED:
+               case TCPS_FIN_WAIT_1:
+               case TCPS_FIN_WAIT_2:
+               case TCPS_CLOSE_WAIT:
+                       so->so_error = ECONNRESET;
+               close:
+                       tp->t_state = TCPS_CLOSED;
+                       tcpstat.tcps_drops++;
+                       tp = tcp_close(tp);
+                       goto drop;
+
+               case TCPS_CLOSING:
+               case TCPS_LAST_ACK:
+               case TCPS_TIME_WAIT:
+                       tp = tcp_close(tp);
+                       goto drop;
+               }
        }
 
        /*
-        * If a SYN is in the window, then this is an
-        * error and we send an RST and drop the connection.
+        * Since we've covered the SYN-SENT and SYN-RECEIVED states above
+        * we must be in a synchronized state.  RFC791 states (under RST
+        * generation) that any unacceptable segment (an out-of-order SYN
+        * qualifies) received in a synchronized state must elicit only an
+        * empty acknowledgment segment ... and the connection remains in
+        * the same state.
         */
        if (tiflags & TH_SYN) {
-               tp = tcp_drop(tp, ECONNRESET);
-               goto dropwithreset;
+               if (tp->rcv_nxt == th->th_seq) {
+                       tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack - 1,
+                           TH_ACK);
+                       if (tcp_saveti)
+                               m_freem(tcp_saveti);
+                       return;
+               }
+                       
+               goto dropafterack_ratelim;
        }
 
        /*
@@ -1978,6 +2003,15 @@
                                        (void) tcp_output(tp);
                                        goto drop;
                                }
+                       } else if (tlen) {
+                               tp->t_dupacks = 0;      /*XXX*/
+                               /* drop very old ACKs unless th_seq matches */
+                               if (th->th_seq != tp->rcv_nxt &&
+                                   SEQ_LT(th->th_ack,
+                                   tp->snd_una - tp->max_sndwnd)) {
+                                       goto drop;
+                               }
+                               break;
                        } else
                                tp->t_dupacks = 0;
                        break;
@@ -2359,6 +2393,20 @@
         */
        if (tiflags & TH_RST)
                goto drop;
+       goto dropafterack2;
+
+dropafterack_ratelim:
+       /*
+        * We may want to rate-limit ACKs against SYN/RST attack.
+        */
+       if (ppsratecheck(&tcp_ackdrop_ppslim_last, &tcp_ackdrop_ppslim_count,
+           tcp_ackdrop_ppslim) == 0) {
+               /* XXX stat */
+               goto drop;
+       }
+       /* ...fall into dropafterack2... */
+
+dropafterack2:
        m_freem(m);
        tp->t_flags |= TF_ACKNOW;
        (void) tcp_output(tp);
diff -r 32235e9509da -r 1bb899db9408 sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c    Tue Apr 20 06:22:39 2004 +0000
+++ b/sys/netinet/tcp_subr.c    Tue Apr 20 20:26:43 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_subr.c,v 1.127.4.4 2003/10/22 06:05:57 jmc Exp $   */
+/*     $NetBSD: tcp_subr.c,v 1.127.4.5 2004/04/20 20:26:43 jmc Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.127.4.4 2003/10/22 06:05:57 jmc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.127.4.5 2004/04/20 20:26:43 jmc Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -187,6 +187,7 @@
 int    tcp_compat_42 = 0;
 #endif
 int    tcp_rst_ppslim = 100;   /* 100pps */
+int    tcp_ackdrop_ppslim = 100;       /* 100pps */
 
 /* tcb hash */
 #ifndef TCBHASHSIZE
diff -r 32235e9509da -r 1bb899db9408 sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h     Tue Apr 20 06:22:39 2004 +0000
+++ b/sys/netinet/tcp_var.h     Tue Apr 20 20:26:43 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_var.h,v 1.90.4.2 2003/10/22 06:06:13 jmc Exp $     */
+/*     $NetBSD: tcp_var.h,v 1.90.4.3 2004/04/20 20:26:57 jmc Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -594,7 +594,8 @@
 #endif
 #define        TCPCTL_RSTPPSLIMIT      24      /* RST pps limit */
 #define        TCPCTL_DELACK_TICKS     25      /* # ticks to delay ACK */
-#define        TCPCTL_MAXID            26
+#define        TCPCTL_ACKDROPRATELIMIT 28      /* SYN/RST -> ACK rate limit */
+#define        TCPCTL_MAXID            29
 
 #define        TCPCTL_NAMES { \
        { 0, 0 }, \
@@ -623,6 +624,9 @@
        { 0, 0 }, \
        { "rstppslimit", CTLTYPE_INT }, \
        { "delack_ticks", CTLTYPE_INT }, \
+       { 0, 0 }, \
+       { 0, 0 }, \
+       { "ackdropppslimit", CTLTYPE_INT }, \
 }
 
 #ifdef _KERNEL
@@ -649,6 +653,7 @@
 extern int tcp_log_refused;    /* log refused connections */
 
 extern int tcp_rst_ppslim;
+extern int tcp_ackdrop_ppslim;
 
 extern int tcp_syn_cache_size;
 extern struct syn_cache_head tcp_syn_cache[];
@@ -681,6 +686,9 @@
        { 0 },                                  \
        { 1, 0, &tcp_rst_ppslim },              \
        { 1, 0, &tcp_delack_ticks },            \
+       { 0 },                                  \
+       { 0 },                                  \
+       { 1, 0, &tcp_ackdrop_ppslim },          \
 }
 
 int     tcp_attach __P((struct socket *));



Home | Main Index | Thread Index | Old Index