]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jan 2013 17:31:57 +0000 (09:31 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Jan 2013 17:31:57 +0000 (09:31 -0800)
added patches:
batman-adv-fix-random-jitter-calculation.patch
inet-fix-kmemleak-in-tcp_v4-6_syn_recv_sock-and-dccp_v4-6_request_recv_sock.patch
net-sched-integer-overflow-fix.patch
tcp-fix-msg_sendpage_notlast-logic.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.4/batman-adv-fix-random-jitter-calculation.patch [new file with mode: 0644]
queue-3.4/inet-fix-kmemleak-in-tcp_v4-6_syn_recv_sock-and-dccp_v4-6_request_recv_sock.patch [new file with mode: 0644]
queue-3.4/net-sched-integer-overflow-fix.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/tcp-fix-msg_sendpage_notlast-logic.patch [new file with mode: 0644]
queue-3.4/tcp-implement-rfc-5961-3.2.patch [new file with mode: 0644]
queue-3.4/tcp-implement-rfc-5961-4.2.patch [new file with mode: 0644]
queue-3.4/tcp-refine-syn-handling-in-tcp_validate_incoming.patch [new file with mode: 0644]
queue-3.4/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch [new file with mode: 0644]
queue-3.4/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch [new file with mode: 0644]

diff --git a/queue-3.4/batman-adv-fix-random-jitter-calculation.patch b/queue-3.4/batman-adv-fix-random-jitter-calculation.patch
new file mode 100644 (file)
index 0000000..fbf0dde
--- /dev/null
@@ -0,0 +1,48 @@
+From 5ebdb766d6b7e70b0981dd28c13fc4f2e1fe9012 Mon Sep 17 00:00:00 2001
+From: Akinobu Mita <akinobu.mita@gmail.com>
+Date: Wed, 26 Dec 2012 02:32:10 +0000
+Subject: batman-adv: fix random jitter calculation
+
+
+From: Akinobu Mita <akinobu.mita@gmail.com>
+
+[ Upstream commit 143cdd8f33909ff5a153e3f02048738c5964ba26 ]
+
+batadv_iv_ogm_emit_send_time() attempts to calculates a random integer
+in the range of 'orig_interval +- BATADV_JITTER' by the below lines.
+
+        msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
+        msecs += (random32() % 2 * BATADV_JITTER);
+
+But it actually gets 'orig_interval' or 'orig_interval - BATADV_JITTER'
+because '%' and '*' have same precedence and associativity is
+left-to-right.
+
+This adds the parentheses at the appropriate position so that it matches
+original intension.
+
+Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
+Acked-by: Antonio Quartulli <ordex@autistici.org>
+Cc: Marek Lindner <lindner_marek@yahoo.de>
+Cc: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
+Cc: Antonio Quartulli <ordex@autistici.org>
+Cc: b.a.t.m.a.n@lists.open-mesh.org
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: netdev@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -72,7 +72,7 @@ static unsigned long bat_iv_ogm_emit_sen
+ {
+       return jiffies + msecs_to_jiffies(
+                  atomic_read(&bat_priv->orig_interval) -
+-                 JITTER + (random32() % 2*JITTER));
++                 JITTER + (random32() % (2*JITTER)));
+ }
+ /* when do we schedule a ogm packet to be sent */
diff --git a/queue-3.4/inet-fix-kmemleak-in-tcp_v4-6_syn_recv_sock-and-dccp_v4-6_request_recv_sock.patch b/queue-3.4/inet-fix-kmemleak-in-tcp_v4-6_syn_recv_sock-and-dccp_v4-6_request_recv_sock.patch
new file mode 100644 (file)
index 0000000..34f0d3d
--- /dev/null
@@ -0,0 +1,160 @@
+From 9f349628e45ffc9249c1687c8dc0ee413c42338e Mon Sep 17 00:00:00 2001
+From: Christoph Paasch <christoph.paasch@uclouvain.be>
+Date: Fri, 14 Dec 2012 04:07:58 +0000
+Subject: inet: Fix kmemleak in tcp_v4/6_syn_recv_sock and dccp_v4/6_request_recv_sock
+
+
+From: Christoph Paasch <christoph.paasch@uclouvain.be>
+
+[ Upstream commit e337e24d6624e74a558aa69071e112a65f7b5758 ]
+
+If in either of the above functions inet_csk_route_child_sock() or
+__inet_inherit_port() fails, the newsk will not be freed:
+
+unreferenced object 0xffff88022e8a92c0 (size 1592):
+  comm "softirq", pid 0, jiffies 4294946244 (age 726.160s)
+  hex dump (first 32 bytes):
+    0a 01 01 01 0a 01 01 02 00 00 00 00 a7 cc 16 00  ................
+    02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00  ................
+  backtrace:
+    [<ffffffff8153d190>] kmemleak_alloc+0x21/0x3e
+    [<ffffffff810ab3e7>] kmem_cache_alloc+0xb5/0xc5
+    [<ffffffff8149b65b>] sk_prot_alloc.isra.53+0x2b/0xcd
+    [<ffffffff8149b784>] sk_clone_lock+0x16/0x21e
+    [<ffffffff814d711a>] inet_csk_clone_lock+0x10/0x7b
+    [<ffffffff814ebbc3>] tcp_create_openreq_child+0x21/0x481
+    [<ffffffff814e8fa5>] tcp_v4_syn_recv_sock+0x3a/0x23b
+    [<ffffffff814ec5ba>] tcp_check_req+0x29f/0x416
+    [<ffffffff814e8e10>] tcp_v4_do_rcv+0x161/0x2bc
+    [<ffffffff814eb917>] tcp_v4_rcv+0x6c9/0x701
+    [<ffffffff814cea9f>] ip_local_deliver_finish+0x70/0xc4
+    [<ffffffff814cec20>] ip_local_deliver+0x4e/0x7f
+    [<ffffffff814ce9f8>] ip_rcv_finish+0x1fc/0x233
+    [<ffffffff814cee68>] ip_rcv+0x217/0x267
+    [<ffffffff814a7bbe>] __netif_receive_skb+0x49e/0x553
+    [<ffffffff814a7cc3>] netif_receive_skb+0x50/0x82
+
+This happens, because sk_clone_lock initializes sk_refcnt to 2, and thus
+a single sock_put() is not enough to free the memory. Additionally, things
+like xfrm, memcg, cookie_values,... may have been initialized.
+We have to free them properly.
+
+This is fixed by forcing a call to tcp_done(), ending up in
+inet_csk_destroy_sock, doing the final sock_put(). tcp_done() is necessary,
+because it ends up doing all the cleanup on xfrm, memcg, cookie_values,
+xfrm,...
+
+Before calling tcp_done, we have to set the socket to SOCK_DEAD, to
+force it entering inet_csk_destroy_sock. To avoid the warning in
+inet_csk_destroy_sock, inet_num has to be set to 0.
+As inet_csk_destroy_sock does a dec on orphan_count, we first have to
+increase it.
+
+Calling tcp_done() allows us to remove the calls to
+tcp_clear_xmit_timer() and tcp_cleanup_congestion_control().
+
+A similar approach is taken for dccp by calling dccp_done().
+
+This is in the kernel since 093d282321 (tproxy: fix hash locking issue
+when using port redirection in __inet_inherit_port()), thus since
+version >= 2.6.37.
+
+Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/inet_connection_sock.h |    1 +
+ net/dccp/ipv4.c                    |    4 ++--
+ net/dccp/ipv6.c                    |    3 ++-
+ net/ipv4/inet_connection_sock.c    |   16 ++++++++++++++++
+ net/ipv4/tcp_ipv4.c                |    6 ++----
+ net/ipv6/tcp_ipv6.c                |    3 ++-
+ 6 files changed, 25 insertions(+), 8 deletions(-)
+
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -317,6 +317,7 @@ extern void inet_csk_reqsk_queue_prune(s
+                                      const unsigned long max_rto);
+ extern void inet_csk_destroy_sock(struct sock *sk);
++extern void inet_csk_prepare_forced_close(struct sock *sk);
+ /*
+  * LISTEN is a special case for poll..
+--- a/net/dccp/ipv4.c
++++ b/net/dccp/ipv4.c
+@@ -435,8 +435,8 @@ exit:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
+       return NULL;
+ put_and_exit:
+-      bh_unlock_sock(newsk);
+-      sock_put(newsk);
++      inet_csk_prepare_forced_close(newsk);
++      dccp_done(newsk);
+       goto exit;
+ }
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -611,7 +611,8 @@ static struct sock *dccp_v6_request_recv
+       newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
+       if (__inet_inherit_port(sk, newsk) < 0) {
+-              sock_put(newsk);
++              inet_csk_prepare_forced_close(newsk);
++              dccp_done(newsk);
+               goto out;
+       }
+       __inet6_hash(newsk, NULL);
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -659,6 +659,22 @@ void inet_csk_destroy_sock(struct sock *
+ }
+ EXPORT_SYMBOL(inet_csk_destroy_sock);
++/* This function allows to force a closure of a socket after the call to
++ * tcp/dccp_create_openreq_child().
++ */
++void inet_csk_prepare_forced_close(struct sock *sk)
++{
++      /* sk_clone_lock locked the socket and set refcnt to 2 */
++      bh_unlock_sock(sk);
++      sock_put(sk);
++
++      /* The below has to be done to allow calling inet_csk_destroy_sock */
++      sock_set_flag(sk, SOCK_DEAD);
++      percpu_counter_inc(sk->sk_prot->orphan_count);
++      inet_sk(sk)->inet_num = 0;
++}
++EXPORT_SYMBOL(inet_csk_prepare_forced_close);
++
+ int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
+ {
+       struct inet_sock *inet = inet_sk(sk);
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -1524,10 +1524,8 @@ exit:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
+       return NULL;
+ put_and_exit:
+-      tcp_clear_xmit_timers(newsk);
+-      tcp_cleanup_congestion_control(newsk);
+-      bh_unlock_sock(newsk);
+-      sock_put(newsk);
++      inet_csk_prepare_forced_close(newsk);
++      tcp_done(newsk);
+       goto exit;
+ }
+ EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -1411,7 +1411,8 @@ static struct sock * tcp_v6_syn_recv_soc
+ #endif
+       if (__inet_inherit_port(sk, newsk) < 0) {
+-              sock_put(newsk);
++              inet_csk_prepare_forced_close(newsk);
++              tcp_done(newsk);
+               goto out;
+       }
+       __inet6_hash(newsk, NULL);
diff --git a/queue-3.4/net-sched-integer-overflow-fix.patch b/queue-3.4/net-sched-integer-overflow-fix.patch
new file mode 100644 (file)
index 0000000..4ce454d
--- /dev/null
@@ -0,0 +1,31 @@
+From f46d30fdf20680f608772ac0f8c83fefd502d21f 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 65134a5758fd2ce3be98a69c34529f4272e2dd13..be8ca4efe28f8b26c1cdb97703fd007c725eb820 100644 (file)
@@ -54,3 +54,12 @@ cgroup-remove-incorrect-dget-dput-pair-in-cgroup_create_dir.patch
 freezer-add-missing-mb-s-to-freezer_count-and-freezer_should_skip.patch
 x86-amd-disable-way-access-filter-on-piledriver-cpus.patch
 sparc-huge_ptep_set_-functions-need-to-call-set_huge_pte_at.patch
+batman-adv-fix-random-jitter-calculation.patch
+inet-fix-kmemleak-in-tcp_v4-6_syn_recv_sock-and-dccp_v4-6_request_recv_sock.patch
+net-sched-integer-overflow-fix.patch
+tcp-fix-msg_sendpage_notlast-logic.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.4/tcp-fix-msg_sendpage_notlast-logic.patch b/queue-3.4/tcp-fix-msg_sendpage_notlast-logic.patch
new file mode 100644 (file)
index 0000000..69141f8
--- /dev/null
@@ -0,0 +1,54 @@
+From 8b19905f4cf882dc5fbc403aa3077b01e33c5b4d Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Sun, 6 Jan 2013 18:21:49 +0000
+Subject: tcp: fix MSG_SENDPAGE_NOTLAST logic
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ae62ca7b03217be5e74759dc6d7698c95df498b3 ]
+
+commit 35f9c09fe9c72e (tcp: tcp_sendpages() should call tcp_push() once)
+added an internal flag : MSG_SENDPAGE_NOTLAST meant to be set on all
+frags but the last one for a splice() call.
+
+The condition used to set the flag in pipe_to_sendpage() relied on
+splice() user passing the exact number of bytes present in the pipe,
+or a smaller one.
+
+But some programs pass an arbitrary high value, and the test fails.
+
+The effect of this bug is a lack of tcp_push() at the end of a
+splice(pipe -> socket) call, and possibly very slow or erratic TCP
+sessions.
+
+We should both test sd->total_len and fact that another fragment
+is in the pipe (pipe->nrbufs > 1)
+
+Many thanks to Willy for providing very clear bug report, bisection
+and test programs.
+
+Reported-by: Willy Tarreau <w@1wt.eu>
+Bisected-by: Willy Tarreau <w@1wt.eu>
+Tested-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/splice.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -696,8 +696,10 @@ static int pipe_to_sendpage(struct pipe_
+               return -EINVAL;
+       more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0;
+-      if (sd->len < sd->total_len)
++
++      if (sd->len < sd->total_len && pipe->nrbufs > 1)
+               more |= MSG_SENDPAGE_NOTLAST;
++
+       return file->f_op->sendpage(file, buf->page, buf->offset,
+                                   sd->len, &pos, more);
+ }
diff --git a/queue-3.4/tcp-implement-rfc-5961-3.2.patch b/queue-3.4/tcp-implement-rfc-5961-3.2.patch
new file mode 100644 (file)
index 0000000..c7447e8
--- /dev/null
@@ -0,0 +1,154 @@
+From 3a0d8556d354b51d7c936b99ee4fb059602293da 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
+@@ -537,6 +537,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
+@@ -234,6 +234,7 @@ enum
+       LINUX_MIB_TCPREQQFULLDROP,              /* TCPReqQFullDrop */
+       LINUX_MIB_TCPRETRANSFAIL,               /* TCPRetransFail */
+       LINUX_MIB_TCPRCVCOALESCE,                       /* TCPRcvCoalesce */
++      LINUX_MIB_TCPCHALLENGEACK,              /* TCPChallengeACK */
+       __LINUX_MIB_MAX
+ };
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -252,6 +252,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
+@@ -258,6 +258,7 @@ static const struct snmp_mib snmp4_net_l
+       SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP),
+       SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL),
+       SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE),
++      SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
+       SNMP_MIB_SENTINEL
+ };
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -590,6 +590,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
+@@ -88,6 +88,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;
+@@ -5265,6 +5268,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.
+  */
+@@ -5301,7 +5321,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.4/tcp-implement-rfc-5961-4.2.patch b/queue-3.4/tcp-implement-rfc-5961-4.2.patch
new file mode 100644 (file)
index 0000000..db6ba8f
--- /dev/null
@@ -0,0 +1,152 @@
+From 9b19208d6b94a410858ad5dadc778f4aec169948 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
+@@ -208,7 +208,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 */
+@@ -235,6 +234,7 @@ enum
+       LINUX_MIB_TCPRETRANSFAIL,               /* TCPRetransFail */
+       LINUX_MIB_TCPRCVCOALESCE,                       /* TCPRcvCoalesce */
+       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),
+@@ -259,6 +258,7 @@ static const struct snmp_mib snmp4_net_l
+       SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL),
+       SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE),
+       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
+@@ -5288,8 +5288,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,
+-                            const struct tcphdr *th, int syn_inerr)
++static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
++                                const struct tcphdr *th, int syn_inerr)
+ {
+       const u8 *hash_location;
+       struct tcp_sock *tp = tcp_sk(sk);
+@@ -5341,20 +5341,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;
+ }
+ /*
+@@ -5384,7 +5386,6 @@ int tcp_rcv_established(struct sock *sk,
+                       const struct tcphdr *th, unsigned int len)
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+-      int res;
+       /*
+        *      Header prediction.
+@@ -5564,9 +5565,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)
+@@ -5876,7 +5876,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;
+@@ -5931,9 +5930,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.4/tcp-refine-syn-handling-in-tcp_validate_incoming.patch b/queue-3.4/tcp-refine-syn-handling-in-tcp_validate_incoming.patch
new file mode 100644 (file)
index 0000000..57568b2
--- /dev/null
@@ -0,0 +1,52 @@
+From 6f9405f9a7f96ea231b46642df9d185b0bc1a53d 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
+@@ -5314,8 +5314,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;
+       }
+@@ -5345,6 +5348,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.4/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch b/queue-3.4/tcp-rfc-5961-5.2-blind-data-injection-attack-mitigation.patch
new file mode 100644 (file)
index 0000000..741c8de
--- /dev/null
@@ -0,0 +1,99 @@
+From da8733e3d96f277b454c8631a7e5baf4844f71a9 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
+@@ -3687,6 +3687,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, const struct sk_buff *skb, int flag)
+ {
+@@ -3706,8 +3724,14 @@ static int tcp_ack(struct sock *sk, cons
+       /* 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).
+@@ -5268,23 +5292,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.4/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch b/queue-3.4/tcp-tcp_replace_ts_recent-should-not-be-called-from-tcp_validate_incoming.patch
new file mode 100644 (file)
index 0000000..97f003f
--- /dev/null
@@ -0,0 +1,74 @@
+From 30b88186c7eeed4f8caa901014164fd337f7fb7b 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
+@@ -5337,11 +5337,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
+@@ -5576,6 +5571,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. */
+@@ -6046,6 +6046,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);