[SRU][X/B/D][CVE-2019-10638] inet: switch IP ID generator to siphash

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[SRU][X/B/D][CVE-2019-10638] inet: switch IP ID generator to siphash

Connor Kuehl
https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-10638.html

From the link above:

"In the Linux kernel before 5.1.7, a device can be tracked by an attacker
using the IP ID values the kernel produces for connection-less protocols
(e.g., UDP and ICMP). When such traffic is sent to multiple destination IP
addresses, it is possible to obtain hash collisions (of indices to the
counter array) and thereby obtain the hashing key (via enumeration). An
attack may be conducted by hosting a crafted web page that uses WebRTC or
gQUIC to force UDP traffic to attacker-controlled IP addresses."

The CVE analysis linked above also identifies another upstream commit required
to address this CVE: 355b98553789 "netns: provide pure entropy for net_hash_mix()"
This commit has already been applied to the affected releases from our upstream
sync process:

 * Xenial update: 4.4.179 upstream stable release
   - https://bugs.launchpad.net/bugs/1828420
 * Bionic update: upstream stable patchset 2019-07-26
   - https://bugs.launchpad.net/bugs/1838116
 * Disco update: 5.0.8 upstream stable release
   - https://bugs.launchpad.net/bugs/1828415

This patch was a clean cherry pick for Bionic and Disco.

For Xenial, I had to pull in the siphash module (can't switch to it if it doesn't
exist) which required minor offset adjustments for high-traffic commit areas like
the Kconfig and Makefile. I set the test hash config option to 'n' to remain
consistent with the other releases. 'N' is also the default suggested value for
the module. Since the other files were new, they didn't require any attention.

The actual patch for this CVE required a minor adjustment to the way it "returns" the
'id' value since it modifies ipv6_proxy_select_ident which has a void return type. The
patch context expects the function signature to be updated to return the value instead
of store it in the skbuf, but this change to the signature doesn't happen until upstream
commit 0c19f846d582 "net: accept UFO datagrams from tuntap and packet" -- I felt the
simplicity of the backport was more justifiable than cherry-picking another patch (and its
possible pre-requisites / other consequences) for a clean cherry-pick.

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][X][CVE-2019-10638][PATCH 1/3] UBUNTU: [Config] CONFIG_TEST_HASH=n

Connor Kuehl
CVE-2019-10638

Signed-off-by: Connor Kuehl <[hidden email]>
---
 debian.master/config/annotations          | 1 +
 debian.master/config/config.common.ubuntu | 1 +
 2 files changed, 2 insertions(+)

diff --git a/debian.master/config/annotations b/debian.master/config/annotations
index adb84bb850dd..38e3a9441ac5 100644
--- a/debian.master/config/annotations
+++ b/debian.master/config/annotations
@@ -8089,6 +8089,7 @@ CONFIG_TEST_HEXDUMP                             policy<{'amd64': 'm', 'arm64': '
 CONFIG_TEST_STRING_HELPERS                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm', 's390x': 'm'}>
 CONFIG_TEST_KSTRTOX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm', 's390x': 'm'}>
 CONFIG_TEST_RHASHTABLE                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'powerpc': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_HASH                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'powerpc': 'n', 'ppc64el': 'n', 's390x': 'n'}>
 #
 CONFIG_LKDTM                                    flag<TESTING> flag<REVIEW>
 CONFIG_TEST_LIST_SORT                           flag<TESTING>
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index e0e1a1c22bc4..16f80d97d93d 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -7848,6 +7848,7 @@ CONFIG_TELCLOCK=m
 CONFIG_TERANETICS_PHY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
+# CONFIG_TEST_HASH is not set
 CONFIG_TEST_HEXDUMP=m
 CONFIG_TEST_KSTRTOX=m
 # CONFIG_TEST_LIST_SORT is not set
--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][X][CVE-2019-10638][PATCH 2/3] siphash: add cryptographically secure PRF

Connor Kuehl
In reply to this post by Connor Kuehl
From: "Jason A. Donenfeld" <[hidden email]>

CVE-2019-10638

SipHash is a 64-bit keyed hash function that is actually a
cryptographically secure PRF, like HMAC. Except SipHash is super fast,
and is meant to be used as a hashtable keyed lookup function, or as a
general PRF for short input use cases, such as sequence numbers or RNG
chaining.

For the first usage:

There are a variety of attacks known as "hashtable poisoning" in which an
attacker forms some data such that the hash of that data will be the
same, and then preceeds to fill up all entries of a hashbucket. This is
a realistic and well-known denial-of-service vector. Currently
hashtables use jhash, which is fast but not secure, and some kind of
rotating key scheme (or none at all, which isn't good). SipHash is meant
as a replacement for jhash in these cases.

There are a modicum of places in the kernel that are vulnerable to
hashtable poisoning attacks, either via userspace vectors or network
vectors, and there's not a reliable mechanism inside the kernel at the
moment to fix it. The first step toward fixing these issues is actually
getting a secure primitive into the kernel for developers to use. Then
we can, bit by bit, port things over to it as deemed appropriate.

While SipHash is extremely fast for a cryptographically secure function,
it is likely a bit slower than the insecure jhash, and so replacements
will be evaluated on a case-by-case basis based on whether or not the
difference in speed is negligible and whether or not the current jhash usage
poses a real security risk.

For the second usage:

A few places in the kernel are using MD5 or SHA1 for creating secure
sequence numbers, syn cookies, port numbers, or fast random numbers.
SipHash is a faster and more fitting, and more secure replacement for MD5
in those situations. Replacing MD5 and SHA1 with SipHash for these uses is
obvious and straight-forward, and so is submitted along with this patch
series. There shouldn't be much of a debate over its efficacy.

Dozens of languages are already using this internally for their hash
tables and PRFs. Some of the BSDs already use this in their kernels.
SipHash is a widely known high-speed solution to a widely known set of
problems, and it's time we catch-up.

Signed-off-by: Jason A. Donenfeld <[hidden email]>
Reviewed-by: Jean-Philippe Aumasson <[hidden email]>
Cc: Linus Torvalds <[hidden email]>
Cc: Eric Biggers <[hidden email]>
Cc: David Laight <[hidden email]>
Cc: Eric Dumazet <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(backported from commit 2c956a60778cbb6a27e0c7a8a52a91378c90e1d1)
[ Connor Kuehl: Minor offset adjustments required due to the high
  traffic nature of things like Kconfig and Makefiles. Had to make
  sure the proper siphash entries made it in to both files since
  the patch context that surrounds it is so different. ]
Signed-off-by: Connor Kuehl <[hidden email]>
---
 Documentation/siphash.txt | 100 ++++++++++++++++
 MAINTAINERS               |   7 ++
 include/linux/siphash.h   |  85 ++++++++++++++
 lib/Kconfig.debug         |  11 ++
 lib/Makefile              |   3 +-
 lib/siphash.c             | 232 ++++++++++++++++++++++++++++++++++++++
 lib/test_siphash.c        | 131 +++++++++++++++++++++
 7 files changed, 568 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/siphash.txt
 create mode 100644 include/linux/siphash.h
 create mode 100644 lib/siphash.c
 create mode 100644 lib/test_siphash.c

diff --git a/Documentation/siphash.txt b/Documentation/siphash.txt
new file mode 100644
index 000000000000..e8e6ddbbaab4
--- /dev/null
+++ b/Documentation/siphash.txt
@@ -0,0 +1,100 @@
+         SipHash - a short input PRF
+-----------------------------------------------
+Written by Jason A. Donenfeld <[hidden email]>
+
+SipHash is a cryptographically secure PRF -- a keyed hash function -- that
+performs very well for short inputs, hence the name. It was designed by
+cryptographers Daniel J. Bernstein and Jean-Philippe Aumasson. It is intended
+as a replacement for some uses of: `jhash`, `md5_transform`, `sha_transform`,
+and so forth.
+
+SipHash takes a secret key filled with randomly generated numbers and either
+an input buffer or several input integers. It spits out an integer that is
+indistinguishable from random. You may then use that integer as part of secure
+sequence numbers, secure cookies, or mask it off for use in a hash table.
+
+1. Generating a key
+
+Keys should always be generated from a cryptographically secure source of
+random numbers, either using get_random_bytes or get_random_once:
+
+siphash_key_t key;
+get_random_bytes(&key, sizeof(key));
+
+If you're not deriving your key from here, you're doing it wrong.
+
+2. Using the functions
+
+There are two variants of the function, one that takes a list of integers, and
+one that takes a buffer:
+
+u64 siphash(const void *data, size_t len, const siphash_key_t *key);
+
+And:
+
+u64 siphash_1u64(u64, const siphash_key_t *key);
+u64 siphash_2u64(u64, u64, const siphash_key_t *key);
+u64 siphash_3u64(u64, u64, u64, const siphash_key_t *key);
+u64 siphash_4u64(u64, u64, u64, u64, const siphash_key_t *key);
+u64 siphash_1u32(u32, const siphash_key_t *key);
+u64 siphash_2u32(u32, u32, const siphash_key_t *key);
+u64 siphash_3u32(u32, u32, u32, const siphash_key_t *key);
+u64 siphash_4u32(u32, u32, u32, u32, const siphash_key_t *key);
+
+If you pass the generic siphash function something of a constant length, it
+will constant fold at compile-time and automatically choose one of the
+optimized functions.
+
+3. Hashtable key function usage:
+
+struct some_hashtable {
+ DECLARE_HASHTABLE(hashtable, 8);
+ siphash_key_t key;
+};
+
+void init_hashtable(struct some_hashtable *table)
+{
+ get_random_bytes(&table->key, sizeof(table->key));
+}
+
+static inline hlist_head *some_hashtable_bucket(struct some_hashtable *table, struct interesting_input *input)
+{
+ return &table->hashtable[siphash(input, sizeof(*input), &table->key) & (HASH_SIZE(table->hashtable) - 1)];
+}
+
+You may then iterate like usual over the returned hash bucket.
+
+4. Security
+
+SipHash has a very high security margin, with its 128-bit key. So long as the
+key is kept secret, it is impossible for an attacker to guess the outputs of
+the function, even if being able to observe many outputs, since 2^128 outputs
+is significant.
+
+Linux implements the "2-4" variant of SipHash.
+
+5. Struct-passing Pitfalls
+
+Often times the XuY functions will not be large enough, and instead you'll
+want to pass a pre-filled struct to siphash. When doing this, it's important
+to always ensure the struct has no padding holes. The easiest way to do this
+is to simply arrange the members of the struct in descending order of size,
+and to use offsetendof() instead of sizeof() for getting the size. For
+performance reasons, if possible, it's probably a good thing to align the
+struct to the right boundary. Here's an example:
+
+const struct {
+ struct in6_addr saddr;
+ u32 counter;
+ u16 dport;
+} __aligned(SIPHASH_ALIGNMENT) combined = {
+ .saddr = *(struct in6_addr *)saddr,
+ .counter = counter,
+ .dport = dport
+};
+u64 h = siphash(&combined, offsetofend(typeof(combined), dport), &secret);
+
+6. Resources
+
+Read the SipHash paper if you're interested in learning more:
+https://131002.net/siphash/siphash.pdf
diff --git a/MAINTAINERS b/MAINTAINERS
index 815734afebca..2f2e39e13a8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9848,6 +9848,13 @@ F: arch/arm/mach-s3c24xx/mach-bast.c
 F: arch/arm/mach-s3c24xx/bast-ide.c
 F: arch/arm/mach-s3c24xx/bast-irq.c
 
+SIPHASH PRF ROUTINES
+M: Jason A. Donenfeld <[hidden email]>
+S: Maintained
+F: lib/siphash.c
+F: lib/test_siphash.c
+F: include/linux/siphash.h
+
 TI DAVINCI MACHINE SUPPORT
 M: Sekhar Nori <[hidden email]>
 M: Kevin Hilman <[hidden email]>
diff --git a/include/linux/siphash.h b/include/linux/siphash.h
new file mode 100644
index 000000000000..feeb29cd113e
--- /dev/null
+++ b/include/linux/siphash.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2016 Jason A. Donenfeld <[hidden email]>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#ifndef _LINUX_SIPHASH_H
+#define _LINUX_SIPHASH_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#define SIPHASH_ALIGNMENT __alignof__(u64)
+typedef struct {
+ u64 key[2];
+} siphash_key_t;
+
+u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key);
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key);
+#endif
+
+u64 siphash_1u64(const u64 a, const siphash_key_t *key);
+u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t *key);
+u64 siphash_3u64(const u64 a, const u64 b, const u64 c,
+ const siphash_key_t *key);
+u64 siphash_4u64(const u64 a, const u64 b, const u64 c, const u64 d,
+ const siphash_key_t *key);
+u64 siphash_1u32(const u32 a, const siphash_key_t *key);
+u64 siphash_3u32(const u32 a, const u32 b, const u32 c,
+ const siphash_key_t *key);
+
+static inline u64 siphash_2u32(const u32 a, const u32 b,
+       const siphash_key_t *key)
+{
+ return siphash_1u64((u64)b << 32 | a, key);
+}
+static inline u64 siphash_4u32(const u32 a, const u32 b, const u32 c,
+       const u32 d, const siphash_key_t *key)
+{
+ return siphash_2u64((u64)b << 32 | a, (u64)d << 32 | c, key);
+}
+
+
+static inline u64 ___siphash_aligned(const __le64 *data, size_t len,
+     const siphash_key_t *key)
+{
+ if (__builtin_constant_p(len) && len == 4)
+ return siphash_1u32(le32_to_cpup((const __le32 *)data), key);
+ if (__builtin_constant_p(len) && len == 8)
+ return siphash_1u64(le64_to_cpu(data[0]), key);
+ if (__builtin_constant_p(len) && len == 16)
+ return siphash_2u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]),
+    key);
+ if (__builtin_constant_p(len) && len == 24)
+ return siphash_3u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]),
+    le64_to_cpu(data[2]), key);
+ if (__builtin_constant_p(len) && len == 32)
+ return siphash_4u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]),
+    le64_to_cpu(data[2]), le64_to_cpu(data[3]),
+    key);
+ return __siphash_aligned(data, len, key);
+}
+
+/**
+ * siphash - compute 64-bit siphash PRF value
+ * @data: buffer to hash
+ * @size: size of @data
+ * @key: the siphash key
+ */
+static inline u64 siphash(const void *data, size_t len,
+  const siphash_key_t *key)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ if (!IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT))
+ return __siphash_unaligned(data, len, key);
+#endif
+ return ___siphash_aligned(data, len, key);
+}
+
+#endif /* _LINUX_SIPHASH_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f0602beeba26..1b7584a64e0a 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1706,6 +1706,17 @@ config TEST_RHASHTABLE
 
   If unsure, say N.
 
+config TEST_HASH
+ tristate "Perform selftest on hash functions"
+ default n
+ help
+  Enable this option to test the kernel's integer (<linux/hash.h>),
+  string (<linux/stringhash.h>), and siphash (<linux/siphash.h>)
+  hash functions on boot (or module load).
+
+  This is intended to help people writing architecture-specific
+  optimized versions.  If unsure, say N.
+
 endmenu # runtime tests
 
 config PROVIDE_OHCI1394_DMA_INIT
diff --git a/lib/Makefile b/lib/Makefile
index cb4f6aa95013..9f044e20e0a8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,7 +13,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
  sha1.o md5.o irq_regs.o argv_split.o \
  proportions.o flex_proportions.o ratelimit.o show_mem.o \
  is_single_threaded.o plist.o decompress.o kobject_uevent.o \
- earlycpio.o seq_buf.o nmi_backtrace.o
+ earlycpio.o seq_buf.o nmi_backtrace.o siphash.o
 
 obj-$(CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS) += usercopy.o
 lib-$(CONFIG_MMU) += ioremap.o
@@ -35,6 +35,7 @@ obj-$(CONFIG_TEST_HEXDUMP) += test-hexdump.o
 obj-y += kstrtox.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
 obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
diff --git a/lib/siphash.c b/lib/siphash.c
new file mode 100644
index 000000000000..c43cf406e71b
--- /dev/null
+++ b/lib/siphash.c
@@ -0,0 +1,232 @@
+/* Copyright (C) 2016 Jason A. Donenfeld <[hidden email]>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#include <linux/siphash.h>
+#include <asm/unaligned.h>
+
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+#include <linux/dcache.h>
+#include <asm/word-at-a-time.h>
+#endif
+
+#define SIPROUND \
+ do { \
+ v0 += v1; v1 = rol64(v1, 13); v1 ^= v0; v0 = rol64(v0, 32); \
+ v2 += v3; v3 = rol64(v3, 16); v3 ^= v2; \
+ v0 += v3; v3 = rol64(v3, 21); v3 ^= v0; \
+ v2 += v1; v1 = rol64(v1, 17); v1 ^= v2; v2 = rol64(v2, 32); \
+ } while (0)
+
+#define PREAMBLE(len) \
+ u64 v0 = 0x736f6d6570736575ULL; \
+ u64 v1 = 0x646f72616e646f6dULL; \
+ u64 v2 = 0x6c7967656e657261ULL; \
+ u64 v3 = 0x7465646279746573ULL; \
+ u64 b = ((u64)(len)) << 56; \
+ v3 ^= key->key[1]; \
+ v2 ^= key->key[0]; \
+ v1 ^= key->key[1]; \
+ v0 ^= key->key[0];
+
+#define POSTAMBLE \
+ v3 ^= b; \
+ SIPROUND; \
+ SIPROUND; \
+ v0 ^= b; \
+ v2 ^= 0xff; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ SIPROUND; \
+ return (v0 ^ v1) ^ (v2 ^ v3);
+
+u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
+{
+ const u8 *end = data + len - (len % sizeof(u64));
+ const u8 left = len & (sizeof(u64) - 1);
+ u64 m;
+ PREAMBLE(len)
+ for (; data != end; data += sizeof(u64)) {
+ m = le64_to_cpup(data);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+ if (left)
+ b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
+  bytemask_from_count(left)));
+#else
+ switch (left) {
+ case 7: b |= ((u64)end[6]) << 48;
+ case 6: b |= ((u64)end[5]) << 40;
+ case 5: b |= ((u64)end[4]) << 32;
+ case 4: b |= le32_to_cpup(data); break;
+ case 3: b |= ((u64)end[2]) << 16;
+ case 2: b |= le16_to_cpup(data); break;
+ case 1: b |= end[0];
+ }
+#endif
+ POSTAMBLE
+}
+EXPORT_SYMBOL(__siphash_aligned);
+
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
+{
+ const u8 *end = data + len - (len % sizeof(u64));
+ const u8 left = len & (sizeof(u64) - 1);
+ u64 m;
+ PREAMBLE(len)
+ for (; data != end; data += sizeof(u64)) {
+ m = get_unaligned_le64(data);
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
+#if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
+ if (left)
+ b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
+  bytemask_from_count(left)));
+#else
+ switch (left) {
+ case 7: b |= ((u64)end[6]) << 48;
+ case 6: b |= ((u64)end[5]) << 40;
+ case 5: b |= ((u64)end[4]) << 32;
+ case 4: b |= get_unaligned_le32(end); break;
+ case 3: b |= ((u64)end[2]) << 16;
+ case 2: b |= get_unaligned_le16(end); break;
+ case 1: b |= end[0];
+ }
+#endif
+ POSTAMBLE
+}
+EXPORT_SYMBOL(__siphash_unaligned);
+#endif
+
+/**
+ * siphash_1u64 - compute 64-bit siphash PRF value of a u64
+ * @first: first u64
+ * @key: the siphash key
+ */
+u64 siphash_1u64(const u64 first, const siphash_key_t *key)
+{
+ PREAMBLE(8)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_1u64);
+
+/**
+ * siphash_2u64 - compute 64-bit siphash PRF value of 2 u64
+ * @first: first u64
+ * @second: second u64
+ * @key: the siphash key
+ */
+u64 siphash_2u64(const u64 first, const u64 second, const siphash_key_t *key)
+{
+ PREAMBLE(16)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ v3 ^= second;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= second;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_2u64);
+
+/**
+ * siphash_3u64 - compute 64-bit siphash PRF value of 3 u64
+ * @first: first u64
+ * @second: second u64
+ * @third: third u64
+ * @key: the siphash key
+ */
+u64 siphash_3u64(const u64 first, const u64 second, const u64 third,
+ const siphash_key_t *key)
+{
+ PREAMBLE(24)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ v3 ^= second;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= second;
+ v3 ^= third;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= third;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_3u64);
+
+/**
+ * siphash_4u64 - compute 64-bit siphash PRF value of 4 u64
+ * @first: first u64
+ * @second: second u64
+ * @third: third u64
+ * @forth: forth u64
+ * @key: the siphash key
+ */
+u64 siphash_4u64(const u64 first, const u64 second, const u64 third,
+ const u64 forth, const siphash_key_t *key)
+{
+ PREAMBLE(32)
+ v3 ^= first;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= first;
+ v3 ^= second;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= second;
+ v3 ^= third;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= third;
+ v3 ^= forth;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= forth;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_4u64);
+
+u64 siphash_1u32(const u32 first, const siphash_key_t *key)
+{
+ PREAMBLE(4)
+ b |= first;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_1u32);
+
+u64 siphash_3u32(const u32 first, const u32 second, const u32 third,
+ const siphash_key_t *key)
+{
+ u64 combined = (u64)second << 32 | first;
+ PREAMBLE(12)
+ v3 ^= combined;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= combined;
+ b |= third;
+ POSTAMBLE
+}
+EXPORT_SYMBOL(siphash_3u32);
diff --git a/lib/test_siphash.c b/lib/test_siphash.c
new file mode 100644
index 000000000000..d972acfc15e4
--- /dev/null
+++ b/lib/test_siphash.c
@@ -0,0 +1,131 @@
+/* Test cases for siphash.c
+ *
+ * Copyright (C) 2016 Jason A. Donenfeld <[hidden email]>. All Rights Reserved.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.
+ *
+ * SipHash: a fast short-input PRF
+ * https://131002.net/siphash/
+ *
+ * This implementation is specifically for SipHash2-4.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/siphash.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+/* Test vectors taken from official reference source available at:
+ *     https://131002.net/siphash/siphash24.c
+ */
+
+static const siphash_key_t test_key_siphash =
+ {{ 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL }};
+
+static const u64 test_vectors_siphash[64] = {
+ 0x726fdb47dd0e0e31ULL, 0x74f839c593dc67fdULL, 0x0d6c8009d9a94f5aULL,
+ 0x85676696d7fb7e2dULL, 0xcf2794e0277187b7ULL, 0x18765564cd99a68dULL,
+ 0xcbc9466e58fee3ceULL, 0xab0200f58b01d137ULL, 0x93f5f5799a932462ULL,
+ 0x9e0082df0ba9e4b0ULL, 0x7a5dbbc594ddb9f3ULL, 0xf4b32f46226bada7ULL,
+ 0x751e8fbc860ee5fbULL, 0x14ea5627c0843d90ULL, 0xf723ca908e7af2eeULL,
+ 0xa129ca6149be45e5ULL, 0x3f2acc7f57c29bdbULL, 0x699ae9f52cbe4794ULL,
+ 0x4bc1b3f0968dd39cULL, 0xbb6dc91da77961bdULL, 0xbed65cf21aa2ee98ULL,
+ 0xd0f2cbb02e3b67c7ULL, 0x93536795e3a33e88ULL, 0xa80c038ccd5ccec8ULL,
+ 0xb8ad50c6f649af94ULL, 0xbce192de8a85b8eaULL, 0x17d835b85bbb15f3ULL,
+ 0x2f2e6163076bcfadULL, 0xde4daaaca71dc9a5ULL, 0xa6a2506687956571ULL,
+ 0xad87a3535c49ef28ULL, 0x32d892fad841c342ULL, 0x7127512f72f27cceULL,
+ 0xa7f32346f95978e3ULL, 0x12e0b01abb051238ULL, 0x15e034d40fa197aeULL,
+ 0x314dffbe0815a3b4ULL, 0x027990f029623981ULL, 0xcadcd4e59ef40c4dULL,
+ 0x9abfd8766a33735cULL, 0x0e3ea96b5304a7d0ULL, 0xad0c42d6fc585992ULL,
+ 0x187306c89bc215a9ULL, 0xd4a60abcf3792b95ULL, 0xf935451de4f21df2ULL,
+ 0xa9538f0419755787ULL, 0xdb9acddff56ca510ULL, 0xd06c98cd5c0975ebULL,
+ 0xe612a3cb9ecba951ULL, 0xc766e62cfcadaf96ULL, 0xee64435a9752fe72ULL,
+ 0xa192d576b245165aULL, 0x0a8787bf8ecb74b2ULL, 0x81b3e73d20b49b6fULL,
+ 0x7fa8220ba3b2eceaULL, 0x245731c13ca42499ULL, 0xb78dbfaf3a8d83bdULL,
+ 0xea1ad565322a1a0bULL, 0x60e61c23a3795013ULL, 0x6606d7e446282b93ULL,
+ 0x6ca4ecb15c5f91e1ULL, 0x9f626da15c9625f3ULL, 0xe51b38608ef25f57ULL,
+ 0x958a324ceb064572ULL
+};
+
+static int __init siphash_test_init(void)
+{
+ u8 in[64] __aligned(SIPHASH_ALIGNMENT);
+ u8 in_unaligned[65] __aligned(SIPHASH_ALIGNMENT);
+ u8 i;
+ int ret = 0;
+
+ for (i = 0; i < 64; ++i) {
+ in[i] = i;
+ in_unaligned[i + 1] = i;
+ if (siphash(in, i, &test_key_siphash) !=
+ test_vectors_siphash[i]) {
+ pr_info("siphash self-test aligned %u: FAIL\n", i + 1);
+ ret = -EINVAL;
+ }
+ if (siphash(in_unaligned + 1, i, &test_key_siphash) !=
+ test_vectors_siphash[i]) {
+ pr_info("siphash self-test unaligned %u: FAIL\n", i + 1);
+ ret = -EINVAL;
+ }
+ }
+ if (siphash_1u64(0x0706050403020100ULL, &test_key_siphash) !=
+ test_vectors_siphash[8]) {
+ pr_info("siphash self-test 1u64: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_2u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL,
+ &test_key_siphash) != test_vectors_siphash[16]) {
+ pr_info("siphash self-test 2u64: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_3u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL,
+ 0x1716151413121110ULL, &test_key_siphash) !=
+ test_vectors_siphash[24]) {
+ pr_info("siphash self-test 3u64: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_4u64(0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL,
+ 0x1716151413121110ULL, 0x1f1e1d1c1b1a1918ULL,
+ &test_key_siphash) != test_vectors_siphash[32]) {
+ pr_info("siphash self-test 4u64: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_1u32(0x03020100U, &test_key_siphash) !=
+ test_vectors_siphash[4]) {
+ pr_info("siphash self-test 1u32: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_2u32(0x03020100U, 0x07060504U, &test_key_siphash) !=
+ test_vectors_siphash[8]) {
+ pr_info("siphash self-test 2u32: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_3u32(0x03020100U, 0x07060504U,
+ 0x0b0a0908U, &test_key_siphash) !=
+ test_vectors_siphash[12]) {
+ pr_info("siphash self-test 3u32: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (siphash_4u32(0x03020100U, 0x07060504U,
+ 0x0b0a0908U, 0x0f0e0d0cU, &test_key_siphash) !=
+ test_vectors_siphash[16]) {
+ pr_info("siphash self-test 4u32: FAIL\n");
+ ret = -EINVAL;
+ }
+ if (!ret)
+ pr_info("self-tests: pass\n");
+ return ret;
+}
+
+static void __exit siphash_test_exit(void)
+{
+}
+
+module_init(siphash_test_init);
+module_exit(siphash_test_exit);
+
+MODULE_AUTHOR("Jason A. Donenfeld <[hidden email]>");
+MODULE_LICENSE("Dual BSD/GPL");
--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][X][CVE-2019-10638][PATCH 3/3] inet: switch IP ID generator to siphash

Connor Kuehl
In reply to this post by Connor Kuehl
From: Eric Dumazet <[hidden email]>

CVE-2019-10638

According to Amit Klein and Benny Pinkas, IP ID generation is too weak
and might be used by attackers.

Even with recent net_hash_mix() fix (netns: provide pure entropy for net_hash_mix())
having 64bit key and Jenkins hash is risky.

It is time to switch to siphash and its 128bit keys.

Signed-off-by: Eric Dumazet <[hidden email]>
Reported-by: Amit Klein <[hidden email]>
Reported-by: Benny Pinkas <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(backported from commit df453700e8d81b1bdafdf684365ee2b9431fb702)
[ Connor Kuehl: Adjusted patch to communicate the id return value
  through the skbuf as the function signature for ipv6_proxy_select_ident
  is still void (whereas the patch context expects it to return a
  value). This function signature change doesn't happen until upstream
  commit: 0c19f846d582 "net: accept UFO datagrams from tuntap and packet" ]
Signed-off-by: Connor Kuehl <[hidden email]>
---
 include/linux/siphash.h  |  5 +++++
 include/net/netns/ipv4.h |  2 ++
 net/ipv4/route.c         | 12 +++++++-----
 net/ipv6/output_core.c   | 30 ++++++++++++++++--------------
 4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/include/linux/siphash.h b/include/linux/siphash.h
index feeb29cd113e..c8c7ae2e687b 100644
--- a/include/linux/siphash.h
+++ b/include/linux/siphash.h
@@ -19,6 +19,11 @@ typedef struct {
  u64 key[2];
 } siphash_key_t;
 
+static inline bool siphash_key_is_zero(const siphash_key_t *key)
+{
+ return !(key->key[0] | key->key[1]);
+}
+
 u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key);
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key);
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 61c38f87ea07..e6f49f22e006 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -8,6 +8,7 @@
 #include <linux/uidgid.h>
 #include <net/inet_frag.h>
 #include <linux/rcupdate.h>
+#include <linux/siphash.h>
 
 struct tcpm_hash_bucket;
 struct ctl_table_header;
@@ -109,5 +110,6 @@ struct netns_ipv4 {
 #endif
 #endif
  atomic_t rt_genid;
+ siphash_key_t ip_id_key;
 };
 #endif
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a669732333fd..7bda59fd7f69 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -509,15 +509,17 @@ EXPORT_SYMBOL(ip_idents_reserve);
 
 void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
 {
- static u32 ip_idents_hashrnd __read_mostly;
  u32 hash, id;
 
- net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
+ /* Note the following code is not safe, but this is okay. */
+ if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key)))
+ get_random_bytes(&net->ipv4.ip_id_key,
+ sizeof(net->ipv4.ip_id_key));
 
- hash = jhash_3words((__force u32)iph->daddr,
+ hash = siphash_3u32((__force u32)iph->daddr,
     (__force u32)iph->saddr,
-    iph->protocol ^ net_hash_mix(net),
-    ip_idents_hashrnd);
+    iph->protocol,
+    &net->ipv4.ip_id_key);
  id = ip_idents_reserve(hash, segs);
  iph->id = htons(id);
 }
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index f99a04674419..6b896cc9604e 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -10,15 +10,25 @@
 #include <net/secure_seq.h>
 #include <linux/netfilter.h>
 
-static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
+static u32 __ipv6_select_ident(struct net *net,
        const struct in6_addr *dst,
        const struct in6_addr *src)
 {
+ const struct {
+ struct in6_addr dst;
+ struct in6_addr src;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .dst = *dst,
+ .src = *src,
+ };
  u32 hash, id;
 
- hash = __ipv6_addr_jhash(dst, hashrnd);
- hash = __ipv6_addr_jhash(src, hash);
- hash ^= net_hash_mix(net);
+ /* Note the following code is not safe, but this is okay. */
+ if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key)))
+ get_random_bytes(&net->ipv4.ip_id_key,
+ sizeof(net->ipv4.ip_id_key));
+
+ hash = siphash(&combined, sizeof(combined), &net->ipv4.ip_id_key);
 
  /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
  * set the hight order instead thus minimizing possible future
@@ -41,7 +51,6 @@ static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
  */
 void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
 {
- static u32 ip6_proxy_idents_hashrnd __read_mostly;
  struct in6_addr buf[2];
  struct in6_addr *addrs;
  u32 id;
@@ -53,11 +62,7 @@ void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
  if (!addrs)
  return;
 
- net_get_random_once(&ip6_proxy_idents_hashrnd,
-    sizeof(ip6_proxy_idents_hashrnd));
-
- id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
- &addrs[1], &addrs[0]);
+ id = __ipv6_select_ident(net, &addrs[1], &addrs[0]);
  skb_shinfo(skb)->ip6_frag_id = htonl(id);
 }
 EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
@@ -66,12 +71,9 @@ __be32 ipv6_select_ident(struct net *net,
  const struct in6_addr *daddr,
  const struct in6_addr *saddr)
 {
- static u32 ip6_idents_hashrnd __read_mostly;
  u32 id;
 
- net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
-
- id = __ipv6_select_ident(net, ip6_idents_hashrnd, daddr, saddr);
+ id = __ipv6_select_ident(net, daddr, saddr);
  return htonl(id);
 }
 EXPORT_SYMBOL(ipv6_select_ident);
--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[SRU][B/D][CVE-2019-10638][PATCH] inet: switch IP ID generator to siphash

Connor Kuehl
In reply to this post by Connor Kuehl
From: Eric Dumazet <[hidden email]>

CVE-2019-10638

According to Amit Klein and Benny Pinkas, IP ID generation is too weak
and might be used by attackers.

Even with recent net_hash_mix() fix (netns: provide pure entropy for net_hash_mix())
having 64bit key and Jenkins hash is risky.

It is time to switch to siphash and its 128bit keys.

Signed-off-by: Eric Dumazet <[hidden email]>
Reported-by: Amit Klein <[hidden email]>
Reported-by: Benny Pinkas <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit df453700e8d81b1bdafdf684365ee2b9431fb702)
Signed-off-by: Connor Kuehl <[hidden email]>
---
 include/linux/siphash.h  |  5 +++++
 include/net/netns/ipv4.h |  2 ++
 net/ipv4/route.c         | 12 +++++++-----
 net/ipv6/output_core.c   | 30 ++++++++++++++++--------------
 4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/include/linux/siphash.h b/include/linux/siphash.h
index fa7a6b9cedbf..bf21591a9e5e 100644
--- a/include/linux/siphash.h
+++ b/include/linux/siphash.h
@@ -21,6 +21,11 @@ typedef struct {
  u64 key[2];
 } siphash_key_t;
 
+static inline bool siphash_key_is_zero(const siphash_key_t *key)
+{
+ return !(key->key[0] | key->key[1]);
+}
+
 u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key);
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key);
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index c23277562a18..2cd8b47cf0ba 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -9,6 +9,7 @@
 #include <linux/uidgid.h>
 #include <net/inet_frag.h>
 #include <linux/rcupdate.h>
+#include <linux/siphash.h>
 
 struct tcpm_hash_bucket;
 struct ctl_table_header;
@@ -206,5 +207,6 @@ struct netns_ipv4 {
  unsigned int ipmr_seq; /* protected by rtnl_mutex */
 
  atomic_t rt_genid;
+ siphash_key_t ip_id_key;
 };
 #endif
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 00dd6c591af0..956290896808 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -517,15 +517,17 @@ EXPORT_SYMBOL(ip_idents_reserve);
 
 void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
 {
- static u32 ip_idents_hashrnd __read_mostly;
  u32 hash, id;
 
- net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
+ /* Note the following code is not safe, but this is okay. */
+ if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key)))
+ get_random_bytes(&net->ipv4.ip_id_key,
+ sizeof(net->ipv4.ip_id_key));
 
- hash = jhash_3words((__force u32)iph->daddr,
+ hash = siphash_3u32((__force u32)iph->daddr,
     (__force u32)iph->saddr,
-    iph->protocol ^ net_hash_mix(net),
-    ip_idents_hashrnd);
+    iph->protocol,
+    &net->ipv4.ip_id_key);
  id = ip_idents_reserve(hash, segs);
  iph->id = htons(id);
 }
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 4fe7c90962dd..868ae23dbae1 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -10,15 +10,25 @@
 #include <net/secure_seq.h>
 #include <linux/netfilter.h>
 
-static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
+static u32 __ipv6_select_ident(struct net *net,
        const struct in6_addr *dst,
        const struct in6_addr *src)
 {
+ const struct {
+ struct in6_addr dst;
+ struct in6_addr src;
+ } __aligned(SIPHASH_ALIGNMENT) combined = {
+ .dst = *dst,
+ .src = *src,
+ };
  u32 hash, id;
 
- hash = __ipv6_addr_jhash(dst, hashrnd);
- hash = __ipv6_addr_jhash(src, hash);
- hash ^= net_hash_mix(net);
+ /* Note the following code is not safe, but this is okay. */
+ if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key)))
+ get_random_bytes(&net->ipv4.ip_id_key,
+ sizeof(net->ipv4.ip_id_key));
+
+ hash = siphash(&combined, sizeof(combined), &net->ipv4.ip_id_key);
 
  /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
  * set the hight order instead thus minimizing possible future
@@ -41,7 +51,6 @@ static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
  */
 __be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
 {
- static u32 ip6_proxy_idents_hashrnd __read_mostly;
  struct in6_addr buf[2];
  struct in6_addr *addrs;
  u32 id;
@@ -53,11 +62,7 @@ __be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
  if (!addrs)
  return 0;
 
- net_get_random_once(&ip6_proxy_idents_hashrnd,
-    sizeof(ip6_proxy_idents_hashrnd));
-
- id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
- &addrs[1], &addrs[0]);
+ id = __ipv6_select_ident(net, &addrs[1], &addrs[0]);
  return htonl(id);
 }
 EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
@@ -66,12 +71,9 @@ __be32 ipv6_select_ident(struct net *net,
  const struct in6_addr *daddr,
  const struct in6_addr *saddr)
 {
- static u32 ip6_idents_hashrnd __read_mostly;
  u32 id;
 
- net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
-
- id = __ipv6_select_ident(net, ip6_idents_hashrnd, daddr, saddr);
+ id = __ipv6_select_ident(net, daddr, saddr);
  return htonl(id);
 }
 EXPORT_SYMBOL(ipv6_select_ident);
--
2.20.1


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [SRU][X/B/D][CVE-2019-10638] inet: switch IP ID generator to siphash

Tyler Hicks-2
In reply to this post by Connor Kuehl
On 2019-08-02 07:14:09, Connor Kuehl wrote:

> https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-10638.html
>
> From the link above:
>
> "In the Linux kernel before 5.1.7, a device can be tracked by an attacker
> using the IP ID values the kernel produces for connection-less protocols
> (e.g., UDP and ICMP). When such traffic is sent to multiple destination IP
> addresses, it is possible to obtain hash collisions (of indices to the
> counter array) and thereby obtain the hashing key (via enumeration). An
> attack may be conducted by hosting a crafted web page that uses WebRTC or
> gQUIC to force UDP traffic to attacker-controlled IP addresses."
>
> The CVE analysis linked above also identifies another upstream commit required
> to address this CVE: 355b98553789 "netns: provide pure entropy for net_hash_mix()"
> This commit has already been applied to the affected releases from our upstream
> sync process:
>
>  * Xenial update: 4.4.179 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828420
>  * Bionic update: upstream stable patchset 2019-07-26
>    - https://bugs.launchpad.net/bugs/1838116
>  * Disco update: 5.0.8 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828415
>
> This patch was a clean cherry pick for Bionic and Disco.
>
> For Xenial, I had to pull in the siphash module (can't switch to it if it doesn't
> exist) which required minor offset adjustments for high-traffic commit areas like
> the Kconfig and Makefile. I set the test hash config option to 'n' to remain
> consistent with the other releases. 'N' is also the default suggested value for
> the module. Since the other files were new, they didn't require any attention.
>
> The actual patch for this CVE required a minor adjustment to the way it "returns" the
> 'id' value since it modifies ipv6_proxy_select_ident which has a void return type. The
> patch context expects the function signature to be updated to return the value instead
> of store it in the skbuf, but this change to the signature doesn't happen until upstream
> commit 0c19f846d582 "net: accept UFO datagrams from tuntap and packet" -- I felt the
> simplicity of the backport was more justifiable than cherry-picking another patch (and its
> possible pre-requisites / other consequences) for a clean cherry-pick.

Acked-by: Tyler Hicks <[hidden email]>

Nice description of the Xenial backport effort. Thanks!

Tyler

>
> --
> kernel-team mailing list
> [hidden email]
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [SRU][X/B/D][CVE-2019-10638] inet: switch IP ID generator to siphash

Kleber Sacilotto de Souza
In reply to this post by Connor Kuehl
On 8/2/19 4:14 PM, Connor Kuehl wrote:

> https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-10638.html
>
> From the link above:
>
> "In the Linux kernel before 5.1.7, a device can be tracked by an attacker
> using the IP ID values the kernel produces for connection-less protocols
> (e.g., UDP and ICMP). When such traffic is sent to multiple destination IP
> addresses, it is possible to obtain hash collisions (of indices to the
> counter array) and thereby obtain the hashing key (via enumeration). An
> attack may be conducted by hosting a crafted web page that uses WebRTC or
> gQUIC to force UDP traffic to attacker-controlled IP addresses."
>
> The CVE analysis linked above also identifies another upstream commit required
> to address this CVE: 355b98553789 "netns: provide pure entropy for net_hash_mix()"
> This commit has already been applied to the affected releases from our upstream
> sync process:
>
>  * Xenial update: 4.4.179 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828420
>  * Bionic update: upstream stable patchset 2019-07-26
>    - https://bugs.launchpad.net/bugs/1838116
>  * Disco update: 5.0.8 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828415
>
> This patch was a clean cherry pick for Bionic and Disco.
>
> For Xenial, I had to pull in the siphash module (can't switch to it if it doesn't
> exist) which required minor offset adjustments for high-traffic commit areas like
> the Kconfig and Makefile. I set the test hash config option to 'n' to remain
> consistent with the other releases. 'N' is also the default suggested value for
> the module. Since the other files were new, they didn't require any attention.
>
> The actual patch for this CVE required a minor adjustment to the way it "returns" the
> 'id' value since it modifies ipv6_proxy_select_ident which has a void return type. The
> patch context expects the function signature to be updated to return the value instead
> of store it in the skbuf, but this change to the signature doesn't happen until upstream
> commit 0c19f846d582 "net: accept UFO datagrams from tuntap and packet" -- I felt the
> simplicity of the backport was more justifiable than cherry-picking another patch (and its
> possible pre-requisites / other consequences) for a clean cherry-pick.
>

Acked-by: Kleber Sacilotto de Souza <[hidden email]>

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

APPLIED/cmt: [SRU][X/B/D][CVE-2019-10638] inet: switch IP ID generator to siphash

Khaled Elmously
In reply to this post by Connor Kuehl
Applied to X.

The B/D patch was already present in B/D by way of stable updates.

Thanks


On 2019-08-02 07:14:09 , Connor Kuehl wrote:

> https://people.canonical.com/~ubuntu-security/cve/2019/CVE-2019-10638.html
>
> From the link above:
>
> "In the Linux kernel before 5.1.7, a device can be tracked by an attacker
> using the IP ID values the kernel produces for connection-less protocols
> (e.g., UDP and ICMP). When such traffic is sent to multiple destination IP
> addresses, it is possible to obtain hash collisions (of indices to the
> counter array) and thereby obtain the hashing key (via enumeration). An
> attack may be conducted by hosting a crafted web page that uses WebRTC or
> gQUIC to force UDP traffic to attacker-controlled IP addresses."
>
> The CVE analysis linked above also identifies another upstream commit required
> to address this CVE: 355b98553789 "netns: provide pure entropy for net_hash_mix()"
> This commit has already been applied to the affected releases from our upstream
> sync process:
>
>  * Xenial update: 4.4.179 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828420
>  * Bionic update: upstream stable patchset 2019-07-26
>    - https://bugs.launchpad.net/bugs/1838116
>  * Disco update: 5.0.8 upstream stable release
>    - https://bugs.launchpad.net/bugs/1828415
>
> This patch was a clean cherry pick for Bionic and Disco.
>
> For Xenial, I had to pull in the siphash module (can't switch to it if it doesn't
> exist) which required minor offset adjustments for high-traffic commit areas like
> the Kconfig and Makefile. I set the test hash config option to 'n' to remain
> consistent with the other releases. 'N' is also the default suggested value for
> the module. Since the other files were new, they didn't require any attention.
>
> The actual patch for this CVE required a minor adjustment to the way it "returns" the
> 'id' value since it modifies ipv6_proxy_select_ident which has a void return type. The
> patch context expects the function signature to be updated to return the value instead
> of store it in the skbuf, but this change to the signature doesn't happen until upstream
> commit 0c19f846d582 "net: accept UFO datagrams from tuntap and packet" -- I felt the
> simplicity of the backport was more justifiable than cherry-picking another patch (and its
> possible pre-requisites / other consequences) for a clean cherry-pick.
>
> --
> kernel-team mailing list
> [hidden email]
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team