]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jan 2013 17:38:27 +0000 (09:38 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jan 2013 17:38:27 +0000 (09:38 -0800)
added patches:
net-sched-integer-overflow-fix.patch
tcp-implement-rfc-5961-3.2.patch
tcp-implement-rfc-5961-4.2.patch
tcp-refine-syn-handling-in-tcp_validate_incoming.patch
tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch
tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch

queue-3.0/net-sched-integer-overflow-fix.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tcp-implement-rfc-5961-3.2.patch [new file with mode: 0644]
queue-3.0/tcp-implement-rfc-5961-4.2.patch [new file with mode: 0644]
queue-3.0/tcp-refine-syn-handling-in-tcp_validate_incoming.patch [new file with mode: 0644]
queue-3.0/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch [new file with mode: 0644]
queue-3.0/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch [new file with mode: 0644]

diff --git a/queue-3.0/net-sched-integer-overflow-fix.patch b/queue-3.0/net-sched-integer-overflow-fix.patch
new file mode 100644 (file)
index 0000000..b779a78
--- /dev/null
@@ -0,0 +1,31 @@
+From f1e20830f328777cee51eb181801d4838eda76fa Mon Sep 17 00:00:00 2001
+From: Stefan Hasko <hasko.stevo@gmail.com>
+Date: Fri, 21 Dec 2012 15:04:59 +0000
+Subject: net: sched: integer overflow fix
+
+
+From: Stefan Hasko <hasko.stevo@gmail.com>
+
+[ Upstream commit d2fe85da52e89b8012ffad010ef352a964725d5f ]
+
+Fixed integer overflow in function htb_dequeue
+
+Signed-off-by: Stefan Hasko <hasko.stevo@gmail.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_htb.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sched/sch_htb.c
++++ b/net/sched/sch_htb.c
+@@ -876,7 +876,7 @@ ok:
+       q->now = psched_get_time();
+       start_at = jiffies;
+-      next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
++      next_event = q->now + 5LLU * PSCHED_TICKS_PER_SEC;
+       for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
+               /* common case optimization - skip event handler quickly */
index d6df1d413c6b08b9702be4822c625a28c9f378fc..bea7e191a1499e8729dc3e005abebc45e8f880a4 100644 (file)
@@ -28,3 +28,9 @@ cgroup-remove-incorrect-dget-dput-pair-in-cgroup_create_dir.patch
 x86-amd-disable-way-access-filter-on-piledriver-cpus.patch
 ftrace-do-not-function-trace-inlined-functions.patch
 sparc-huge_ptep_set_-functions-need-to-call-set_huge_pte_at.patch
+net-sched-integer-overflow-fix.patch
+tcp-implement-rfc-5961-3.2.patch
+tcp-implement-rfc-5961-4.2.patch
+tcp-refine-syn-handling-in-tcp_validate_incoming.patch
+tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch
+tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch
diff --git a/queue-3.0/tcp-implement-rfc-5961-3.2.patch b/queue-3.0/tcp-implement-rfc-5961-3.2.patch
new file mode 100644 (file)
index 0000000..b93fe6b
--- /dev/null
@@ -0,0 +1,154 @@
+From 0d39f43963ef47bb3d3af0a331ba17825f07b1fb Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 17 Jul 2012 10:13:05 +0200
+Subject: tcp: implement RFC 5961 3.2
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 282f23c6ee343126156dd41218b22ece96d747e3 ]
+
+Implement the RFC 5691 mitigation against Blind
+Reset attack using RST bit.
+
+Idea is to validate incoming RST sequence,
+to match RCV.NXT value, instead of previouly accepted
+window : (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND)
+
+If sequence is in window but not an exact match, send
+a "challenge ACK", so that the other part can resend an
+RST with the appropriate sequence.
+
+Add a new sysctl, tcp_challenge_ack_limit, to limit
+number of challenge ACK sent per second.
+
+Add a new SNMP counter to count number of challenge acks sent.
+(netstat -s | grep TCPChallengeACK)
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Kiran Kumar Kella <kkiran@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/networking/ip-sysctl.txt |    5 +++++
+ include/linux/snmp.h                   |    1 +
+ include/net/tcp.h                      |    1 +
+ net/ipv4/proc.c                        |    1 +
+ net/ipv4/sysctl_net_ipv4.c             |    7 +++++++
+ net/ipv4/tcp_input.c                   |   31 ++++++++++++++++++++++++++++++-
+ 6 files changed, 45 insertions(+), 1 deletion(-)
+
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -534,6 +534,11 @@ tcp_thin_dupack - BOOLEAN
+       Documentation/networking/tcp-thin.txt
+       Default: 0
++tcp_challenge_ack_limit - INTEGER
++      Limits number of Challenge ACK sent per second, as recommended
++      in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
++      Default: 100
++
+ UDP variables:
+ udp_mem - vector of 3 INTEGERs: min, pressure, max
+--- a/include/linux/snmp.h
++++ b/include/linux/snmp.h
+@@ -231,6 +231,7 @@ enum
+       LINUX_MIB_TCPDEFERACCEPTDROP,
+       LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
+       LINUX_MIB_TCPTIMEWAITOVERFLOW,          /* TCPTimeWaitOverflow */
++      LINUX_MIB_TCPCHALLENGEACK,              /* TCPChallengeACK */
+       __LINUX_MIB_MAX
+ };
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -246,6 +246,7 @@ extern int sysctl_tcp_max_ssthresh;
+ extern int sysctl_tcp_cookie_size;
+ extern int sysctl_tcp_thin_linear_timeouts;
+ extern int sysctl_tcp_thin_dupack;
++extern int sysctl_tcp_challenge_ack_limit;
+ extern atomic_long_t tcp_memory_allocated;
+ extern struct percpu_counter tcp_sockets_allocated;
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -254,6 +254,7 @@ static const struct snmp_mib snmp4_net_l
+       SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
+       SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
+       SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
++      SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
+       SNMP_MIB_SENTINEL
+ };
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -566,6 +566,13 @@ static struct ctl_table ipv4_table[] = {
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
++      {
++              .procname       = "tcp_challenge_ack_limit",
++              .data           = &sysctl_tcp_challenge_ack_limit,
++              .maxlen         = sizeof(int),
++              .mode           = 0644,
++              .proc_handler   = proc_dointvec
++      },
+ #ifdef CONFIG_NET_DMA
+       {
+               .procname       = "tcp_dma_copybreak",
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -86,6 +86,9 @@ int sysctl_tcp_app_win __read_mostly = 3
+ int sysctl_tcp_adv_win_scale __read_mostly = 1;
+ EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
++/* rfc5961 challenge ack rate limiting */
++int sysctl_tcp_challenge_ack_limit = 100;
++
+ int sysctl_tcp_stdurg __read_mostly;
+ int sysctl_tcp_rfc1337 __read_mostly;
+ int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
+@@ -5165,6 +5168,23 @@ out:
+ }
+ #endif /* CONFIG_NET_DMA */
++static void tcp_send_challenge_ack(struct sock *sk)
++{
++      /* unprotected vars, we dont care of overwrites */
++      static u32 challenge_timestamp;
++      static unsigned int challenge_count;
++      u32 now = jiffies / HZ;
++
++      if (now != challenge_timestamp) {
++              challenge_timestamp = now;
++              challenge_count = 0;
++      }
++      if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
++              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
++              tcp_send_ack(sk);
++      }
++}
++
+ /* Does PAWS and seqno based validation of an incoming segment, flags will
+  * play significant role here.
+  */
+@@ -5201,7 +5221,16 @@ static int tcp_validate_incoming(struct
+       /* Step 2: check RST bit */
+       if (th->rst) {
+-              tcp_reset(sk);
++              /* RFC 5961 3.2 :
++               * If sequence number exactly matches RCV.NXT, then
++               *     RESET the connection
++               * else
++               *     Send a challenge ACK
++               */
++              if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt)
++                      tcp_reset(sk);
++              else
++                      tcp_send_challenge_ack(sk);
+               goto discard;
+       }
diff --git a/queue-3.0/tcp-implement-rfc-5961-4.2.patch b/queue-3.0/tcp-implement-rfc-5961-4.2.patch
new file mode 100644 (file)
index 0000000..4a16eee
--- /dev/null
@@ -0,0 +1,152 @@
+From c273d8204931e8a0be07e04dcf6b00fb73532db3 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 17 Jul 2012 01:41:30 +0000
+Subject: tcp: implement RFC 5961 4.2
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 0c24604b68fc7810d429d6c3657b6f148270e528 ]
+
+Implement the RFC 5691 mitigation against Blind
+Reset attack using SYN bit.
+
+Section 4.2 of RFC 5961 advises to send a Challenge ACK and drop
+incoming packet, instead of resetting the session.
+
+Add a new SNMP counter to count number of challenge acks sent
+in response to SYN packets.
+(netstat -s | grep TCPSYNChallenge)
+
+Remove obsolete TCPAbortOnSyn, since we no longer abort a TCP session
+because of a SYN flag.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Kiran Kumar Kella <kkiran@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/snmp.h |    2 +-
+ net/ipv4/proc.c      |    2 +-
+ net/ipv4/tcp_input.c |   32 +++++++++++++++-----------------
+ 3 files changed, 17 insertions(+), 19 deletions(-)
+
+--- a/include/linux/snmp.h
++++ b/include/linux/snmp.h
+@@ -209,7 +209,6 @@ enum
+       LINUX_MIB_TCPDSACKOFOSENT,              /* TCPDSACKOfoSent */
+       LINUX_MIB_TCPDSACKRECV,                 /* TCPDSACKRecv */
+       LINUX_MIB_TCPDSACKOFORECV,              /* TCPDSACKOfoRecv */
+-      LINUX_MIB_TCPABORTONSYN,                /* TCPAbortOnSyn */
+       LINUX_MIB_TCPABORTONDATA,               /* TCPAbortOnData */
+       LINUX_MIB_TCPABORTONCLOSE,              /* TCPAbortOnClose */
+       LINUX_MIB_TCPABORTONMEMORY,             /* TCPAbortOnMemory */
+@@ -232,6 +231,7 @@ enum
+       LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
+       LINUX_MIB_TCPTIMEWAITOVERFLOW,          /* TCPTimeWaitOverflow */
+       LINUX_MIB_TCPCHALLENGEACK,              /* TCPChallengeACK */
++      LINUX_MIB_TCPSYNCHALLENGE,              /* TCPSYNChallenge */
+       __LINUX_MIB_MAX
+ };
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -232,7 +232,6 @@ static const struct snmp_mib snmp4_net_l
+       SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT),
+       SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV),
+       SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV),
+-      SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN),
+       SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA),
+       SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE),
+       SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY),
+@@ -255,6 +254,7 @@ static const struct snmp_mib snmp4_net_l
+       SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
+       SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
+       SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
++      SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE),
+       SNMP_MIB_SENTINEL
+ };
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -5188,8 +5188,8 @@ static void tcp_send_challenge_ack(struc
+ /* Does PAWS and seqno based validation of an incoming segment, flags will
+  * play significant role here.
+  */
+-static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
+-                            struct tcphdr *th, int syn_inerr)
++static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
++                                struct tcphdr *th, int syn_inerr)
+ {
+       u8 *hash_location;
+       struct tcp_sock *tp = tcp_sk(sk);
+@@ -5241,20 +5241,22 @@ static int tcp_validate_incoming(struct
+       /* step 3: check security and precedence [ignored] */
+-      /* step 4: Check for a SYN in window. */
+-      if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
++      /* step 4: Check for a SYN
++       * RFC 5691 4.2 : Send a challenge ack
++       */
++      if (th->syn) {
+               if (syn_inerr)
+                       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
+-              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN);
+-              tcp_reset(sk);
+-              return -1;
++              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
++              tcp_send_challenge_ack(sk);
++              goto discard;
+       }
+-      return 1;
++      return true;
+ discard:
+       __kfree_skb(skb);
+-      return 0;
++      return false;
+ }
+ /*
+@@ -5284,7 +5286,6 @@ int tcp_rcv_established(struct sock *sk,
+                       struct tcphdr *th, unsigned len)
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+-      int res;
+       /*
+        *      Header prediction.
+@@ -5464,9 +5465,8 @@ slow_path:
+        *      Standard slow path.
+        */
+-      res = tcp_validate_incoming(sk, skb, th, 1);
+-      if (res <= 0)
+-              return -res;
++      if (!tcp_validate_incoming(sk, skb, th, 1))
++              return 0;
+ step5:
+       if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+@@ -5776,7 +5776,6 @@ int tcp_rcv_state_process(struct sock *s
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       int queued = 0;
+-      int res;
+       tp->rx_opt.saw_tstamp = 0;
+@@ -5831,9 +5830,8 @@ int tcp_rcv_state_process(struct sock *s
+               return 0;
+       }
+-      res = tcp_validate_incoming(sk, skb, th, 0);
+-      if (res <= 0)
+-              return -res;
++      if (!tcp_validate_incoming(sk, skb, th, 0))
++              return 0;
+       /* step 5: check the ACK field */
+       if (th->ack) {
diff --git a/queue-3.0/tcp-refine-syn-handling-in-tcp_validate_incoming.patch b/queue-3.0/tcp-refine-syn-handling-in-tcp_validate_incoming.patch
new file mode 100644 (file)
index 0000000..e8b923e
--- /dev/null
@@ -0,0 +1,52 @@
+From 3e4726b5d8d90396d1ce6adbb8416c04479666bb Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 17 Jul 2012 12:29:30 +0000
+Subject: tcp: refine SYN handling in tcp_validate_incoming
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit e371589917011efe6ff8c7dfb4e9e81934ac5855 ]
+
+Followup of commit 0c24604b68fc (tcp: implement RFC 5961 4.2)
+
+As reported by Vijay Subramanian, we should send a challenge ACK
+instead of a dup ack if a SYN flag is set on a packet received out of
+window.
+
+This permits the ratelimiting to work as intended, and to increase
+correct SNMP counters.
+
+Suggested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Vijay Subramanian <subramanian.vijay@gmail.com>
+Cc: Kiran Kumar Kella <kkiran@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -5214,8 +5214,11 @@ static bool tcp_validate_incoming(struct
+                * an acknowledgment should be sent in reply (unless the RST
+                * bit is set, if so drop the segment and return)".
+                */
+-              if (!th->rst)
++              if (!th->rst) {
++                      if (th->syn)
++                              goto syn_challenge;
+                       tcp_send_dupack(sk, skb);
++              }
+               goto discard;
+       }
+@@ -5245,6 +5248,7 @@ static bool tcp_validate_incoming(struct
+        * RFC 5691 4.2 : Send a challenge ack
+        */
+       if (th->syn) {
++syn_challenge:
+               if (syn_inerr)
+                       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
diff --git a/queue-3.0/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch b/queue-3.0/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch
new file mode 100644 (file)
index 0000000..a2891db
--- /dev/null
@@ -0,0 +1,99 @@
+From d0c918f5163e2ce743146675d2c12ac315b69eeb Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Sun, 21 Oct 2012 19:57:11 +0000
+Subject: tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 354e4aa391ed50a4d827ff6fc11e0667d0859b25 ]
+
+RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation]
+
+  All TCP stacks MAY implement the following mitigation.  TCP stacks
+  that implement this mitigation MUST add an additional input check to
+  any incoming segment.  The ACK value is considered acceptable only if
+  it is in the range of ((SND.UNA - MAX.SND.WND) <= SEG.ACK <=
+  SND.NXT).  All incoming segments whose ACK value doesn't satisfy the
+  above condition MUST be discarded and an ACK sent back.
+
+Move tcp_send_challenge_ack() before tcp_ack() to avoid a forward
+declaration.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Neal Cardwell <ncardwell@google.com>
+Cc: Yuchung Cheng <ycheng@google.com>
+Cc: Jerry Chu <hkchu@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c |   43 +++++++++++++++++++++++++------------------
+ 1 file changed, 25 insertions(+), 18 deletions(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3636,6 +3636,24 @@ static int tcp_process_frto(struct sock
+       return 0;
+ }
++/* RFC 5961 7 [ACK Throttling] */
++static void tcp_send_challenge_ack(struct sock *sk)
++{
++      /* unprotected vars, we dont care of overwrites */
++      static u32 challenge_timestamp;
++      static unsigned int challenge_count;
++      u32 now = jiffies / HZ;
++
++      if (now != challenge_timestamp) {
++              challenge_timestamp = now;
++              challenge_count = 0;
++      }
++      if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
++              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
++              tcp_send_ack(sk);
++      }
++}
++
+ /* This routine deals with incoming acks, but not outgoing ones. */
+ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
+ {
+@@ -3652,8 +3670,14 @@ static int tcp_ack(struct sock *sk, stru
+       /* If the ack is older than previous acks
+        * then we can probably ignore it.
+        */
+-      if (before(ack, prior_snd_una))
++      if (before(ack, prior_snd_una)) {
++              /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
++              if (before(ack, prior_snd_una - tp->max_window)) {
++                      tcp_send_challenge_ack(sk);
++                      return -1;
++              }
+               goto old_ack;
++      }
+       /* If the ack includes data we haven't sent yet, discard
+        * this segment (RFC793 Section 3.9).
+@@ -5168,23 +5192,6 @@ out:
+ }
+ #endif /* CONFIG_NET_DMA */
+-static void tcp_send_challenge_ack(struct sock *sk)
+-{
+-      /* unprotected vars, we dont care of overwrites */
+-      static u32 challenge_timestamp;
+-      static unsigned int challenge_count;
+-      u32 now = jiffies / HZ;
+-
+-      if (now != challenge_timestamp) {
+-              challenge_timestamp = now;
+-              challenge_count = 0;
+-      }
+-      if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+-              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
+-              tcp_send_ack(sk);
+-      }
+-}
+-
+ /* Does PAWS and seqno based validation of an incoming segment, flags will
+  * play significant role here.
+  */
diff --git a/queue-3.0/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch b/queue-3.0/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch
new file mode 100644 (file)
index 0000000..151786f
--- /dev/null
@@ -0,0 +1,74 @@
+From e5cf6017a12d2941a9b98ef7e50aa3816d98ee6a Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 13 Nov 2012 05:37:18 +0000
+Subject: tcp: tcp_replace_ts_recent() should not be called from tcp_validate_incoming()
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit bd090dfc634ddd711a5fbd0cadc6e0ab4977bcaf ]
+
+We added support for RFC 5961 in latest kernels but TCP fails
+to perform exhaustive check of ACK sequence.
+
+We can update our view of peer tsval from a frame that is
+later discarded by tcp_ack()
+
+This makes timestamps enabled sessions vulnerable to injection of
+a high tsval : peers start an ACK storm, since the victim
+sends a dupack each time it receives an ACK from the other peer.
+
+As tcp_validate_incoming() is called before tcp_ack(), we should
+not peform tcp_replace_ts_recent() from it, and let callers do it
+at the right time.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Neal Cardwell <ncardwell@google.com>
+Cc: Yuchung Cheng <ycheng@google.com>
+Cc: Nandita Dukkipati <nanditad@google.com>
+Cc: H.K. Jerry Chu <hkchu@google.com>
+Cc: Romain Francoise <romain@orebokech.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_input.c |   15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -5237,11 +5237,6 @@ static bool tcp_validate_incoming(struct
+               goto discard;
+       }
+-      /* ts_recent update must be made after we are sure that the packet
+-       * is in window.
+-       */
+-      tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+-
+       /* step 3: check security and precedence [ignored] */
+       /* step 4: Check for a SYN
+@@ -5476,6 +5471,11 @@ step5:
+       if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+               goto discard;
++      /* ts_recent update must be made after we are sure that the packet
++       * is in window.
++       */
++      tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
++
+       tcp_rcv_rtt_measure_ts(sk, skb);
+       /* Process urgent data. */
+@@ -5952,6 +5952,11 @@ int tcp_rcv_state_process(struct sock *s
+       } else
+               goto discard;
++      /* ts_recent update must be made after we are sure that the packet
++       * is in window.
++       */
++      tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
++
+       /* step 6: check the URG bit */
+       tcp_urg(sk, skb, th);