From 208350505de2fd0c974b1af1ec072a5a36b27f1a Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Mon, 22 Aug 2016 12:53:36 +0200 Subject: kernel-net: CVE-2016-5696 tcp: make challenge acks less predictable net/ipv4/tcp_input.c in the Linux kernel before 4.7 does not properly determine the rate of challenge ACK segments, which makes it easier for man-in-the-middle attackers to hijack TCP sessions via a blind in-window attack. References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-5696 https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ patch/?id=860c53258e634c54f70252c352bae7bac30724a9 Signed-off-by: Sona Sarmadi Signed-off-by: Martin Borg --- recipes-kernel/linux/files/net-CVE-2016-5696.patch | 98 ++++++++++++++++++++++ recipes-kernel/linux/linux-qoriq_3.12.bbappend | 1 + 2 files changed, 99 insertions(+) create mode 100644 recipes-kernel/linux/files/net-CVE-2016-5696.patch diff --git a/recipes-kernel/linux/files/net-CVE-2016-5696.patch b/recipes-kernel/linux/files/net-CVE-2016-5696.patch new file mode 100644 index 0000000..3be480a --- /dev/null +++ b/recipes-kernel/linux/files/net-CVE-2016-5696.patch @@ -0,0 +1,98 @@ +From: Eric Dumazet +Date: Sun, 10 Jul 2016 10:04:02 +0200 +Subject: [PATCH] tcp: make challenge acks less predictable + +[ Upstream commit 75ff39ccc1bd5d3c455b6822ab09e533c551f758 ] + +Yue Cao claims that current host rate limiting of challenge ACKS +(RFC 5961) could leak enough information to allow a patient attacker +to hijack TCP sessions. He will soon provide details in an academic +paper. + +This patch increases the default limit from 100 to 1000, and adds +some randomization so that the attacker can no longer hijack +sessions without spending a considerable amount of probes. + +Based on initial analysis and patch from Linus. + +Note that we also have per socket rate limiting, so it is tempting +to remove the host limit in the future. + +v2: randomize the count of challenge acks per second, not the period. + +CVE: CVE-2016-5696 +Upstream-Status: Backport +[This patch was bakported from 3.14 branch, added "prandom_u32_max" in +"include/linux/random.h" since this was not implemented in 3.12 branch] + +Fixes: 282f23c6ee34 ("tcp: implement RFC 5961 3.2") +Reported-by: Yue Cao +Signed-off-by: Eric Dumazet +Suggested-by: Linus Torvalds +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Neal Cardwell +Acked-by: Yuchung Cheng +Signed-off-by: David S. Miller +Signed-off-by: Sona Sarmadi +--- +diff -ruN a/include/linux/random.h b/include/linux/random.h +--- a/include/linux/random.h 2016-08-22 11:03:21.140946372 +0200 ++++ b/include/linux/random.h 2016-08-22 10:45:43.294241721 +0200 +@@ -33,6 +33,23 @@ + u32 prandom_u32_state(struct rnd_state *); + void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes); + ++/** ++ * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) ++ * @ep_ro: right open interval endpoint ++ * ++ * Returns a pseudo-random number that is in interval [0, ep_ro). Note ++ * that the result depends on PRNG being well distributed in [0, ~0U] ++ * u32 space. Here we use maximally equidistributed combined Tausworthe ++ * generator, that is, prandom_u32(). This is useful when requesting a ++ * random index of an array containing ep_ro elements, for example. ++ * ++ * Returns: pseudo-random number in interval [0, ep_ro) ++ */ ++static inline u32 prandom_u32_max(u32 ep_ro) ++{ ++ return (u32)(((u64) prandom_u32() * ep_ro) >> 32); ++} ++ + /* + * Handle minimum values for seeds + */ +diff -ruN a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +--- a/net/ipv4/tcp_input.c 2016-08-22 11:03:25.296627413 +0200 ++++ b/net/ipv4/tcp_input.c 2016-08-22 11:27:20.522438724 +0200 +@@ -87,7 +87,7 @@ + EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); + + /* rfc5961 challenge ack rate limiting */ +-int sysctl_tcp_challenge_ack_limit = 100; ++int sysctl_tcp_challenge_ack_limit = 1000; + + int sysctl_tcp_stdurg __read_mostly; + int sysctl_tcp_rfc1337 __read_mostly; +@@ -3245,12 +3245,18 @@ + static u32 challenge_timestamp; + static unsigned int challenge_count; + u32 now = jiffies / HZ; ++ u32 count; + + if (now != challenge_timestamp) { ++ u32 half = (sysctl_tcp_challenge_ack_limit + 1) >> 1; ++ + challenge_timestamp = now; +- challenge_count = 0; ++ challenge_count = half + ++ prandom_u32_max(sysctl_tcp_challenge_ack_limit); + } +- if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { ++ count = challenge_count; ++ if (count > 0) { ++ challenge_count = count - 1; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); + tcp_send_ack(sk); + } diff --git a/recipes-kernel/linux/linux-qoriq_3.12.bbappend b/recipes-kernel/linux/linux-qoriq_3.12.bbappend index 0ed4489..a963007 100644 --- a/recipes-kernel/linux/linux-qoriq_3.12.bbappend +++ b/recipes-kernel/linux/linux-qoriq_3.12.bbappend @@ -5,5 +5,6 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI += "file://ppp-CVE-2015-8569.patch \ file://net-CVE-2015-8543.patch \ file://net-CVE-2016-2070.patch \ + file://net-CVE-2016-5696.patch \ " -- cgit v1.2.3-54-g00ecf