]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 May 2017 09:13:20 +0000 (11:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 May 2017 09:13:20 +0000 (11:13 +0200)
added patches:
bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch
bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch
bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch
bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch
geneve-fix-incorrect-setting-of-udp-checksum-flag.patch
ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch
ipv6-initialize-route-null-entry-in-addrconf_init.patch
ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch
net-ipv6-do-not-duplicate-dad-on-link-up.patch
net-macb-fix-phy-interrupt-parsing.patch
net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch
net-usb-qmi_wwan-add-telit-me910-support.patch
rtnetlink-nul-terminate-ifla_phys_port_name-string.patch
tcp-do-not-inherit-fastopen_req-from-parent.patch
tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch
tcp-fix-wraparound-issue-in-tcp_lp.patch
tcp-randomize-timestamps-on-syncookies.patch

18 files changed:
queue-4.11/bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch [new file with mode: 0644]
queue-4.11/bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch [new file with mode: 0644]
queue-4.11/bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch [new file with mode: 0644]
queue-4.11/bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch [new file with mode: 0644]
queue-4.11/geneve-fix-incorrect-setting-of-udp-checksum-flag.patch [new file with mode: 0644]
queue-4.11/ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch [new file with mode: 0644]
queue-4.11/ipv6-initialize-route-null-entry-in-addrconf_init.patch [new file with mode: 0644]
queue-4.11/ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch [new file with mode: 0644]
queue-4.11/net-ipv6-do-not-duplicate-dad-on-link-up.patch [new file with mode: 0644]
queue-4.11/net-macb-fix-phy-interrupt-parsing.patch [new file with mode: 0644]
queue-4.11/net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch [new file with mode: 0644]
queue-4.11/net-usb-qmi_wwan-add-telit-me910-support.patch [new file with mode: 0644]
queue-4.11/rtnetlink-nul-terminate-ifla_phys_port_name-string.patch [new file with mode: 0644]
queue-4.11/series
queue-4.11/tcp-do-not-inherit-fastopen_req-from-parent.patch [new file with mode: 0644]
queue-4.11/tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch [new file with mode: 0644]
queue-4.11/tcp-fix-wraparound-issue-in-tcp_lp.patch [new file with mode: 0644]
queue-4.11/tcp-randomize-timestamps-on-syncookies.patch [new file with mode: 0644]

diff --git a/queue-4.11/bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch b/queue-4.11/bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch
new file mode 100644 (file)
index 0000000..29e4ab7
--- /dev/null
@@ -0,0 +1,34 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Sat, 6 May 2017 03:49:01 +0300
+Subject: bnxt_en: allocate enough space for ->ntp_fltr_bmap
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+
+[ Upstream commit ac45bd93a5035c2f39c9862b8b6ed692db0fdc87 ]
+
+We have the number of longs, but we need to calculate the number of
+bytes required.
+
+Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -3000,7 +3000,8 @@ static int bnxt_alloc_ntp_fltrs(struct b
+               INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]);
+       bp->ntp_fltr_count = 0;
+-      bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
++      bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
++                                  sizeof(long),
+                                   GFP_KERNEL);
+       if (!bp->ntp_fltr_bmap)
diff --git a/queue-4.11/bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch b/queue-4.11/bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch
new file mode 100644 (file)
index 0000000..eca3696
--- /dev/null
@@ -0,0 +1,144 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Tue, 2 May 2017 20:34:54 +0200
+Subject: bpf, arm64: fix jit branch offset related to ldimm64
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+
+[ Upstream commit ddc665a4bb4b728b4e6ecec8db1b64efa9184b9c ]
+
+When the instruction right before the branch destination is
+a 64 bit load immediate, we currently calculate the wrong
+jump offset in the ctx->offset[] array as we only account
+one instruction slot for the 64 bit load immediate although
+it uses two BPF instructions. Fix it up by setting the offset
+into the right slot after we incremented the index.
+
+Before (ldimm64 test 1):
+
+  [...]
+  00000020:  52800007  mov w7, #0x0 // #0
+  00000024:  d2800060  mov x0, #0x3 // #3
+  00000028:  d2800041  mov x1, #0x2 // #2
+  0000002c:  eb01001f  cmp x0, x1
+  00000030:  54ffff82  b.cs 0x00000020
+  00000034:  d29fffe7  mov x7, #0xffff // #65535
+  00000038:  f2bfffe7  movk x7, #0xffff, lsl #16
+  0000003c:  f2dfffe7  movk x7, #0xffff, lsl #32
+  00000040:  f2ffffe7  movk x7, #0xffff, lsl #48
+  00000044:  d29dddc7  mov x7, #0xeeee // #61166
+  00000048:  f2bdddc7  movk x7, #0xeeee, lsl #16
+  0000004c:  f2ddddc7  movk x7, #0xeeee, lsl #32
+  00000050:  f2fdddc7  movk x7, #0xeeee, lsl #48
+  [...]
+
+After (ldimm64 test 1):
+
+  [...]
+  00000020:  52800007  mov w7, #0x0 // #0
+  00000024:  d2800060  mov x0, #0x3 // #3
+  00000028:  d2800041  mov x1, #0x2 // #2
+  0000002c:  eb01001f  cmp x0, x1
+  00000030:  540000a2  b.cs 0x00000044
+  00000034:  d29fffe7  mov x7, #0xffff // #65535
+  00000038:  f2bfffe7  movk x7, #0xffff, lsl #16
+  0000003c:  f2dfffe7  movk x7, #0xffff, lsl #32
+  00000040:  f2ffffe7  movk x7, #0xffff, lsl #48
+  00000044:  d29dddc7  mov x7, #0xeeee // #61166
+  00000048:  f2bdddc7  movk x7, #0xeeee, lsl #16
+  0000004c:  f2ddddc7  movk x7, #0xeeee, lsl #32
+  00000050:  f2fdddc7  movk x7, #0xeeee, lsl #48
+  [...]
+
+Also, add a couple of test cases to make sure JITs pass
+this test. Tested on Cavium ThunderX ARMv8. The added
+test cases all pass after the fix.
+
+Fixes: 8eee539ddea0 ("arm64: bpf: fix out-of-bounds read in bpf2a64_offset()")
+Reported-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Cc: Xi Wang <xi.wang@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/net/bpf_jit_comp.c |    8 +++----
+ lib/test_bpf.c                |   45 ++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 49 insertions(+), 4 deletions(-)
+
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -779,14 +779,14 @@ static int build_body(struct jit_ctx *ct
+               int ret;
+               ret = build_insn(insn, ctx);
+-
+-              if (ctx->image == NULL)
+-                      ctx->offset[i] = ctx->idx;
+-
+               if (ret > 0) {
+                       i++;
++                      if (ctx->image == NULL)
++                              ctx->offset[i] = ctx->idx;
+                       continue;
+               }
++              if (ctx->image == NULL)
++                      ctx->offset[i] = ctx->idx;
+               if (ret)
+                       return ret;
+       }
+--- a/lib/test_bpf.c
++++ b/lib/test_bpf.c
+@@ -4656,6 +4656,51 @@ static struct bpf_test tests[] = {
+               { },
+               { { 0, 1 } },
+       },
++      {
++              /* Mainly testing JIT + imm64 here. */
++              "JMP_JGE_X: ldimm64 test 1",
++              .u.insns_int = {
++                      BPF_ALU32_IMM(BPF_MOV, R0, 0),
++                      BPF_LD_IMM64(R1, 3),
++                      BPF_LD_IMM64(R2, 2),
++                      BPF_JMP_REG(BPF_JGE, R1, R2, 2),
++                      BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
++                      BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
++                      BPF_EXIT_INSN(),
++              },
++              INTERNAL,
++              { },
++              { { 0, 0xeeeeeeeeU } },
++      },
++      {
++              "JMP_JGE_X: ldimm64 test 2",
++              .u.insns_int = {
++                      BPF_ALU32_IMM(BPF_MOV, R0, 0),
++                      BPF_LD_IMM64(R1, 3),
++                      BPF_LD_IMM64(R2, 2),
++                      BPF_JMP_REG(BPF_JGE, R1, R2, 0),
++                      BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
++                      BPF_EXIT_INSN(),
++              },
++              INTERNAL,
++              { },
++              { { 0, 0xffffffffU } },
++      },
++      {
++              "JMP_JGE_X: ldimm64 test 3",
++              .u.insns_int = {
++                      BPF_ALU32_IMM(BPF_MOV, R0, 1),
++                      BPF_LD_IMM64(R1, 3),
++                      BPF_LD_IMM64(R2, 2),
++                      BPF_JMP_REG(BPF_JGE, R1, R2, 4),
++                      BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
++                      BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
++                      BPF_EXIT_INSN(),
++              },
++              INTERNAL,
++              { },
++              { { 0, 1 } },
++      },
+       /* BPF_JMP | BPF_JNE | BPF_X */
+       {
+               "JMP_JNE_X: if (3 != 2) return 1",
diff --git a/queue-4.11/bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch b/queue-4.11/bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch
new file mode 100644 (file)
index 0000000..f7b9e4a
--- /dev/null
@@ -0,0 +1,79 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Mon, 8 May 2017 00:04:09 +0200
+Subject: bpf: don't let ldimm64 leak map addresses on unprivileged
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+
+[ Upstream commit 0d0e57697f162da4aa218b5feafe614fb666db07 ]
+
+The patch fixes two things at once:
+
+1) It checks the env->allow_ptr_leaks and only prints the map address to
+   the log if we have the privileges to do so, otherwise it just dumps 0
+   as we would when kptr_restrict is enabled on %pK. Given the latter is
+   off by default and not every distro sets it, I don't want to rely on
+   this, hence the 0 by default for unprivileged.
+
+2) Printing of ldimm64 in the verifier log is currently broken in that
+   we don't print the full immediate, but only the 32 bit part of the
+   first insn part for ldimm64. Thus, fix this up as well; it's okay to
+   access, since we verified all ldimm64 earlier already (including just
+   constants) through replace_map_fd_with_map_ptr().
+
+Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs")
+Fixes: cbd357008604 ("bpf: verifier (add ability to receive verification log)")
+Reported-by: Jann Horn <jannh@google.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c |   21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -296,7 +296,8 @@ static const char *const bpf_jmp_string[
+       [BPF_EXIT >> 4] = "exit",
+ };
+-static void print_bpf_insn(struct bpf_insn *insn)
++static void print_bpf_insn(const struct bpf_verifier_env *env,
++                         const struct bpf_insn *insn)
+ {
+       u8 class = BPF_CLASS(insn->code);
+@@ -360,9 +361,19 @@ static void print_bpf_insn(struct bpf_in
+                               insn->code,
+                               bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
+                               insn->src_reg, insn->imm);
+-              } else if (BPF_MODE(insn->code) == BPF_IMM) {
+-                      verbose("(%02x) r%d = 0x%x\n",
+-                              insn->code, insn->dst_reg, insn->imm);
++              } else if (BPF_MODE(insn->code) == BPF_IMM &&
++                         BPF_SIZE(insn->code) == BPF_DW) {
++                      /* At this point, we already made sure that the second
++                       * part of the ldimm64 insn is accessible.
++                       */
++                      u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
++                      bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
++
++                      if (map_ptr && !env->allow_ptr_leaks)
++                              imm = 0;
++
++                      verbose("(%02x) r%d = 0x%llx\n", insn->code,
++                              insn->dst_reg, (unsigned long long)imm);
+               } else {
+                       verbose("BUG_ld_%02x\n", insn->code);
+                       return;
+@@ -2835,7 +2846,7 @@ static int do_check(struct bpf_verifier_
+               if (log_level) {
+                       verbose("%d: ", insn_idx);
+-                      print_bpf_insn(insn);
++                      print_bpf_insn(env, insn);
+               }
+               err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);
diff --git a/queue-4.11/bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch b/queue-4.11/bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch
new file mode 100644 (file)
index 0000000..b0575dd
--- /dev/null
@@ -0,0 +1,91 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Yonghong Song <yhs@fb.com>
+Date: Sat, 29 Apr 2017 22:52:42 -0700
+Subject: bpf: enhance verifier to understand stack pointer arithmetic
+
+From: Yonghong Song <yhs@fb.com>
+
+
+[ Upstream commit 332270fdc8b6fba07d059a9ad44df9e1a2ad4529 ]
+
+llvm 4.0 and above generates the code like below:
+....
+440: (b7) r1 = 15
+441: (05) goto pc+73
+515: (79) r6 = *(u64 *)(r10 -152)
+516: (bf) r7 = r10
+517: (07) r7 += -112
+518: (bf) r2 = r7
+519: (0f) r2 += r1
+520: (71) r1 = *(u8 *)(r8 +0)
+521: (73) *(u8 *)(r2 +45) = r1
+....
+and the verifier complains "R2 invalid mem access 'inv'" for insn #521.
+This is because verifier marks register r2 as unknown value after #519
+where r2 is a stack pointer and r1 holds a constant value.
+
+Teach verifier to recognize "stack_ptr + imm" and
+"stack_ptr + reg with const val" as valid stack_ptr with new offset.
+
+Signed-off-by: Yonghong Song <yhs@fb.com>
+Acked-by: Martin KaFai Lau <kafai@fb.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/verifier.c                       |   11 +++++++++++
+ tools/testing/selftests/bpf/test_verifier.c |   18 ++++++++++++------
+ 2 files changed, 23 insertions(+), 6 deletions(-)
+
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -1911,6 +1911,17 @@ static int check_alu_op(struct bpf_verif
+                       return 0;
+               } else if (opcode == BPF_ADD &&
+                          BPF_CLASS(insn->code) == BPF_ALU64 &&
++                         dst_reg->type == PTR_TO_STACK &&
++                         ((BPF_SRC(insn->code) == BPF_X &&
++                           regs[insn->src_reg].type == CONST_IMM) ||
++                          BPF_SRC(insn->code) == BPF_K)) {
++                      if (BPF_SRC(insn->code) == BPF_X)
++                              dst_reg->imm += regs[insn->src_reg].imm;
++                      else
++                              dst_reg->imm += insn->imm;
++                      return 0;
++              } else if (opcode == BPF_ADD &&
++                         BPF_CLASS(insn->code) == BPF_ALU64 &&
+                          (dst_reg->type == PTR_TO_PACKET ||
+                           (BPF_SRC(insn->code) == BPF_X &&
+                            regs[insn->src_reg].type == PTR_TO_PACKET))) {
+--- a/tools/testing/selftests/bpf/test_verifier.c
++++ b/tools/testing/selftests/bpf/test_verifier.c
+@@ -1809,16 +1809,22 @@ static struct bpf_test tests[] = {
+               .result = ACCEPT,
+       },
+       {
+-              "unpriv: obfuscate stack pointer",
++              "stack pointer arithmetic",
+               .insns = {
+-                      BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+-                      BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+-                      BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
++                      BPF_MOV64_IMM(BPF_REG_1, 4),
++                      BPF_JMP_IMM(BPF_JA, 0, 0, 0),
++                      BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
++                      BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10),
++                      BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10),
++                      BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
++                      BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
++                      BPF_ST_MEM(0, BPF_REG_2, 4, 0),
++                      BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
++                      BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
++                      BPF_ST_MEM(0, BPF_REG_2, 4, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+-              .errstr_unpriv = "R2 pointer arithmetic",
+-              .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
+       {
diff --git a/queue-4.11/geneve-fix-incorrect-setting-of-udp-checksum-flag.patch b/queue-4.11/geneve-fix-incorrect-setting-of-udp-checksum-flag.patch
new file mode 100644 (file)
index 0000000..a97b63b
--- /dev/null
@@ -0,0 +1,42 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Girish Moodalbail <girish.moodalbail@oracle.com>
+Date: Thu, 27 Apr 2017 14:11:53 -0700
+Subject: geneve: fix incorrect setting of UDP checksum flag
+
+From: Girish Moodalbail <girish.moodalbail@oracle.com>
+
+
+[ Upstream commit 5e0740c445e6ae4026f5e52456ff8d0be9725183 ]
+
+Creating a geneve link with 'udpcsum' set results in a creation of link
+for which UDP checksum will NOT be computed on outbound packets, as can
+be seen below.
+
+11: gen0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
+    link/ether c2:85:27:b6:b4:15 brd ff:ff:ff:ff:ff:ff promiscuity 0
+    geneve id 200 remote 192.168.13.1 dstport 6081 noudpcsum
+
+Similarly, creating a link with 'noudpcsum' set results in a creation
+of link for which UDP checksum will be computed on outbound packets.
+
+Fixes: 9b4437a5b870 ("geneve: Unify LWT and netdev handling.")
+Signed-off-by: Girish Moodalbail <girish.moodalbail@oracle.com>
+Acked-by: Pravin B Shelar <pshelar@ovn.org>
+Acked-by: Lance Richardson <lrichard@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/geneve.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -1244,7 +1244,7 @@ static int geneve_newlink(struct net *ne
+               metadata = true;
+       if (data[IFLA_GENEVE_UDP_CSUM] &&
+-          !nla_get_u8(data[IFLA_GENEVE_UDP_CSUM]))
++          nla_get_u8(data[IFLA_GENEVE_UDP_CSUM]))
+               info.key.tun_flags |= TUNNEL_CSUM;
+       if (data[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] &&
diff --git a/queue-4.11/ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch b/queue-4.11/ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch
new file mode 100644 (file)
index 0000000..2298a7f
--- /dev/null
@@ -0,0 +1,112 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Alexander Potapenko <glider@google.com>
+Date: Wed, 3 May 2017 17:06:58 +0200
+Subject: ipv4, ipv6: ensure raw socket message is big enough to hold an IP header
+
+From: Alexander Potapenko <glider@google.com>
+
+
+[ Upstream commit 86f4c90a1c5c1493f07f2d12c1079f5bf01936f2 ]
+
+raw_send_hdrinc() and rawv6_send_hdrinc() expect that the buffer copied
+from the userspace contains the IPv4/IPv6 header, so if too few bytes are
+copied, parts of the header may remain uninitialized.
+
+This bug has been detected with KMSAN.
+
+For the record, the KMSAN report:
+
+==================================================================
+BUG: KMSAN: use of unitialized memory in nf_ct_frag6_gather+0xf5a/0x44a0
+inter: 0
+CPU: 0 PID: 1036 Comm: probe Not tainted 4.11.0-rc5+ #2455
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:16
+ dump_stack+0x143/0x1b0 lib/dump_stack.c:52
+ kmsan_report+0x16b/0x1e0 mm/kmsan/kmsan.c:1078
+ __kmsan_warning_32+0x5c/0xa0 mm/kmsan/kmsan_instr.c:510
+ nf_ct_frag6_gather+0xf5a/0x44a0 net/ipv6/netfilter/nf_conntrack_reasm.c:577
+ ipv6_defrag+0x1d9/0x280 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c:68
+ nf_hook_entry_hookfn ./include/linux/netfilter.h:102
+ nf_hook_slow+0x13f/0x3c0 net/netfilter/core.c:310
+ nf_hook ./include/linux/netfilter.h:212
+ NF_HOOK ./include/linux/netfilter.h:255
+ rawv6_send_hdrinc net/ipv6/raw.c:673
+ rawv6_sendmsg+0x2fcb/0x41a0 net/ipv6/raw.c:919
+ inet_sendmsg+0x3f8/0x6d0 net/ipv4/af_inet.c:762
+ sock_sendmsg_nosec net/socket.c:633
+ sock_sendmsg net/socket.c:643
+ SYSC_sendto+0x6a5/0x7c0 net/socket.c:1696
+ SyS_sendto+0xbc/0xe0 net/socket.c:1664
+ do_syscall_64+0x72/0xa0 arch/x86/entry/common.c:285
+ entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:246
+RIP: 0033:0x436e03
+RSP: 002b:00007ffce48baf38 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+RAX: ffffffffffffffda RBX: 00000000004002b0 RCX: 0000000000436e03
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
+RBP: 00007ffce48baf90 R08: 00007ffce48baf50 R09: 000000000000001c
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 0000000000401790 R14: 0000000000401820 R15: 0000000000000000
+origin: 00000000d9400053
+ save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
+ kmsan_save_stack_with_flags mm/kmsan/kmsan.c:362
+ kmsan_internal_poison_shadow+0xb1/0x1a0 mm/kmsan/kmsan.c:257
+ kmsan_poison_shadow+0x6d/0xc0 mm/kmsan/kmsan.c:270
+ slab_alloc_node mm/slub.c:2735
+ __kmalloc_node_track_caller+0x1f4/0x390 mm/slub.c:4341
+ __kmalloc_reserve net/core/skbuff.c:138
+ __alloc_skb+0x2cd/0x740 net/core/skbuff.c:231
+ alloc_skb ./include/linux/skbuff.h:933
+ alloc_skb_with_frags+0x209/0xbc0 net/core/skbuff.c:4678
+ sock_alloc_send_pskb+0x9ff/0xe00 net/core/sock.c:1903
+ sock_alloc_send_skb+0xe4/0x100 net/core/sock.c:1920
+ rawv6_send_hdrinc net/ipv6/raw.c:638
+ rawv6_sendmsg+0x2918/0x41a0 net/ipv6/raw.c:919
+ inet_sendmsg+0x3f8/0x6d0 net/ipv4/af_inet.c:762
+ sock_sendmsg_nosec net/socket.c:633
+ sock_sendmsg net/socket.c:643
+ SYSC_sendto+0x6a5/0x7c0 net/socket.c:1696
+ SyS_sendto+0xbc/0xe0 net/socket.c:1664
+ do_syscall_64+0x72/0xa0 arch/x86/entry/common.c:285
+ return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:246
+==================================================================
+
+, triggered by the following syscalls:
+  socket(PF_INET6, SOCK_RAW, IPPROTO_RAW) = 3
+  sendto(3, NULL, 0, 0, {sa_family=AF_INET6, sin6_port=htons(0), inet_pton(AF_INET6, "ff00::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EPERM
+
+A similar report is triggered in net/ipv4/raw.c if we use a PF_INET socket
+instead of a PF_INET6 one.
+
+Signed-off-by: Alexander Potapenko <glider@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/raw.c |    3 +++
+ net/ipv6/raw.c |    2 ++
+ 2 files changed, 5 insertions(+)
+
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -358,6 +358,9 @@ static int raw_send_hdrinc(struct sock *
+                              rt->dst.dev->mtu);
+               return -EMSGSIZE;
+       }
++      if (length < sizeof(struct iphdr))
++              return -EINVAL;
++
+       if (flags&MSG_PROBE)
+               goto out;
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -632,6 +632,8 @@ static int rawv6_send_hdrinc(struct sock
+               ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
+               return -EMSGSIZE;
+       }
++      if (length < sizeof(struct ipv6hdr))
++              return -EINVAL;
+       if (flags&MSG_PROBE)
+               goto out;
diff --git a/queue-4.11/ipv6-initialize-route-null-entry-in-addrconf_init.patch b/queue-4.11/ipv6-initialize-route-null-entry-in-addrconf_init.patch
new file mode 100644 (file)
index 0000000..109eee8
--- /dev/null
@@ -0,0 +1,97 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Wed, 3 May 2017 22:07:31 -0700
+Subject: ipv6: initialize route null entry in addrconf_init()
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+
+[ Upstream commit 2f460933f58eee3393aba64f0f6d14acb08d1724 ]
+
+Andrey reported a crash on init_net.ipv6.ip6_null_entry->rt6i_idev
+since it is always NULL.
+
+This is clearly wrong, we have code to initialize it to loopback_dev,
+unfortunately the order is still not correct.
+
+loopback_dev is registered very early during boot, we lose a chance
+to re-initialize it in notifier. addrconf_init() is called after
+ip6_route_init(), which means we have no chance to correct it.
+
+Fix it by moving this initialization explicitly after
+ipv6_add_dev(init_net.loopback_dev) in addrconf_init().
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/ip6_route.h |    1 +
+ net/ipv6/addrconf.c     |    2 ++
+ net/ipv6/route.c        |   26 +++++++++++++++-----------
+ 3 files changed, 18 insertions(+), 11 deletions(-)
+
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -84,6 +84,7 @@ struct dst_entry *ip6_route_lookup(struc
+ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
+                              int ifindex, struct flowi6 *fl6, int flags);
++void ip6_route_init_special_entries(void);
+ int ip6_route_init(void);
+ void ip6_route_cleanup(void);
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -6409,6 +6409,8 @@ int __init addrconf_init(void)
+               goto errlo;
+       }
++      ip6_route_init_special_entries();
++
+       for (i = 0; i < IN6_ADDR_HSIZE; i++)
+               INIT_HLIST_HEAD(&inet6_addr_lst[i]);
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -4022,6 +4022,21 @@ static struct notifier_block ip6_route_d
+       .priority = 0,
+ };
++void __init ip6_route_init_special_entries(void)
++{
++      /* Registering of the loopback is done before this portion of code,
++       * the loopback reference in rt6_info will not be taken, do it
++       * manually for init_net */
++      init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
++      init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
++      init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
++      init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++      init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
++      init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++  #endif
++}
++
+ int __init ip6_route_init(void)
+ {
+       int ret;
+@@ -4048,17 +4063,6 @@ int __init ip6_route_init(void)
+       ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
+-      /* Registering of the loopback is done before this portion of code,
+-       * the loopback reference in rt6_info will not be taken, do it
+-       * manually for init_net */
+-      init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
+-      init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-      init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
+-      init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-      init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
+-      init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-  #endif
+       ret = fib6_init();
+       if (ret)
+               goto out_register_subsys;
diff --git a/queue-4.11/ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch b/queue-4.11/ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch
new file mode 100644 (file)
index 0000000..2bca3b0
--- /dev/null
@@ -0,0 +1,101 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Mon, 8 May 2017 10:12:13 -0700
+Subject: ipv6: reorder ip6_route_dev_notifier after ipv6_dev_notf
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+
+[ Upstream commit 242d3a49a2a1a71d8eb9f953db1bcaa9d698ce00 ]
+
+For each netns (except init_net), we initialize its null entry
+in 3 places:
+
+1) The template itself, as we use kmemdup()
+2) Code around dst_init_metrics() in ip6_route_net_init()
+3) ip6_route_dev_notify(), which is supposed to initialize it after
+   loopback registers
+
+Unfortunately the last one still happens in a wrong order because
+we expect to initialize net->ipv6.ip6_null_entry->rt6i_idev to
+net->loopback_dev's idev, thus we have to do that after we add
+idev to loopback. However, this notifier has priority == 0 same as
+ipv6_dev_notf, and ipv6_dev_notf is registered after
+ip6_route_dev_notifier so it is called actually after
+ip6_route_dev_notifier. This is similar to commit 2f460933f58e
+("ipv6: initialize route null entry in addrconf_init()") which
+fixes init_net.
+
+Fix it by picking a smaller priority for ip6_route_dev_notifier.
+Also, we have to release the refcnt accordingly when unregistering
+loopback_dev because device exit functions are called before subsys
+exit functions.
+
+Acked-by: David Ahern <dsahern@gmail.com>
+Tested-by: David Ahern <dsahern@gmail.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/addrconf.h |    2 ++
+ net/ipv6/addrconf.c    |    1 +
+ net/ipv6/route.c       |   13 +++++++++++--
+ 3 files changed, 14 insertions(+), 2 deletions(-)
+
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -20,6 +20,8 @@
+ #define ADDRCONF_TIMER_FUZZ           (HZ / 4)
+ #define ADDRCONF_TIMER_FUZZ_MAX               (HZ)
++#define ADDRCONF_NOTIFY_PRIORITY      0
++
+ #include <linux/in.h>
+ #include <linux/in6.h>
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -3516,6 +3516,7 @@ static int addrconf_notify(struct notifi
+  */
+ static struct notifier_block ipv6_dev_notf = {
+       .notifier_call = addrconf_notify,
++      .priority = ADDRCONF_NOTIFY_PRIORITY,
+ };
+ static void addrconf_type_change(struct net_device *dev, unsigned long event)
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -3704,7 +3704,10 @@ static int ip6_route_dev_notify(struct n
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct net *net = dev_net(dev);
+-      if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
++      if (!(dev->flags & IFF_LOOPBACK))
++              return NOTIFY_OK;
++
++      if (event == NETDEV_REGISTER) {
+               net->ipv6.ip6_null_entry->dst.dev = dev;
+               net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+@@ -3713,6 +3716,12 @@ static int ip6_route_dev_notify(struct n
+               net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
+               net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
+ #endif
++       } else if (event == NETDEV_UNREGISTER) {
++              in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++              in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
++              in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
++#endif
+       }
+       return NOTIFY_OK;
+@@ -4019,7 +4028,7 @@ static struct pernet_operations ip6_rout
+ static struct notifier_block ip6_route_dev_notifier = {
+       .notifier_call = ip6_route_dev_notify,
+-      .priority = 0,
++      .priority = ADDRCONF_NOTIFY_PRIORITY - 10,
+ };
+ void __init ip6_route_init_special_entries(void)
diff --git a/queue-4.11/net-ipv6-do-not-duplicate-dad-on-link-up.patch b/queue-4.11/net-ipv6-do-not-duplicate-dad-on-link-up.patch
new file mode 100644 (file)
index 0000000..3da2e14
--- /dev/null
@@ -0,0 +1,119 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: David Ahern <dsahern@gmail.com>
+Date: Tue, 2 May 2017 14:43:44 -0700
+Subject: net: ipv6: Do not duplicate DAD on link up
+
+From: David Ahern <dsahern@gmail.com>
+
+
+[ Upstream commit 6d717134a1a6e1b34a7d0d70e953037bc2642046 ]
+
+Andrey reported a warning triggered by the rcu code:
+
+------------[ cut here ]------------
+WARNING: CPU: 1 PID: 5911 at lib/debugobjects.c:289
+debug_print_object+0x175/0x210
+ODEBUG: activate active (active state 1) object type: rcu_head hint:
+        (null)
+Modules linked in:
+CPU: 1 PID: 5911 Comm: a.out Not tainted 4.11.0-rc8+ #271
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:16
+ dump_stack+0x192/0x22d lib/dump_stack.c:52
+ __warn+0x19f/0x1e0 kernel/panic.c:549
+ warn_slowpath_fmt+0xe0/0x120 kernel/panic.c:564
+ debug_print_object+0x175/0x210 lib/debugobjects.c:286
+ debug_object_activate+0x574/0x7e0 lib/debugobjects.c:442
+ debug_rcu_head_queue kernel/rcu/rcu.h:75
+ __call_rcu.constprop.76+0xff/0x9c0 kernel/rcu/tree.c:3229
+ call_rcu_sched+0x12/0x20 kernel/rcu/tree.c:3288
+ rt6_rcu_free net/ipv6/ip6_fib.c:158
+ rt6_release+0x1ea/0x290 net/ipv6/ip6_fib.c:188
+ fib6_del_route net/ipv6/ip6_fib.c:1461
+ fib6_del+0xa42/0xdc0 net/ipv6/ip6_fib.c:1500
+ __ip6_del_rt+0x100/0x160 net/ipv6/route.c:2174
+ ip6_del_rt+0x140/0x1b0 net/ipv6/route.c:2187
+ __ipv6_ifa_notify+0x269/0x780 net/ipv6/addrconf.c:5520
+ addrconf_ifdown+0xe60/0x1a20 net/ipv6/addrconf.c:3672
+...
+
+Andrey's reproducer program runs in a very tight loop, calling
+'unshare -n' and then spawning 2 sets of 14 threads running random ioctl
+calls. The relevant networking sequence:
+
+1. New network namespace created via unshare -n
+- ip6tnl0 device is created in down state
+
+2. address added to ip6tnl0
+- equivalent to ip -6 addr add dev ip6tnl0 fd00::bb/1
+- DAD is started on the address and when it completes the host
+  route is inserted into the FIB
+
+3. ip6tnl0 is brought up
+- the new fixup_permanent_addr function restarts DAD on the address
+
+4. exit namespace
+- teardown / cleanup sequence starts
+- once in a blue moon, lo teardown appears to happen BEFORE teardown
+  of ip6tunl0
+  + down on 'lo' removes the host route from the FIB since the dst->dev
+    for the route is loobback
+  + host route added to rcu callback list
+    * rcu callback has not run yet, so rt is NOT on the gc list so it has
+      NOT been marked obsolete
+
+5. in parallel to 4. worker_thread runs addrconf_dad_completed
+- DAD on the address on ip6tnl0 completes
+- calls ipv6_ifa_notify which inserts the host route
+
+All of that happens very quickly. The result is that a host route that
+has been deleted from the IPv6 FIB and added to the RCU list is re-inserted
+into the FIB.
+
+The exit namespace eventually gets to cleaning up ip6tnl0 which removes the
+host route from the FIB again, calls the rcu function for cleanup -- and
+triggers the double rcu trace.
+
+The root cause is duplicate DAD on the address -- steps 2 and 3. Arguably,
+DAD should not be started in step 2. The interface is in the down state,
+so it can not really send out requests for the address which makes starting
+DAD pointless.
+
+Since the second DAD was introduced by a recent change, seems appropriate
+to use it for the Fixes tag and have the fixup function only start DAD for
+addresses in the PREDAD state which occurs in addrconf_ifdown if the
+address is retained.
+
+Big thanks to Andrey for isolating a reliable reproducer for this problem.
+Fixes: f1705ec197e7 ("net: ipv6: Make address flushing on ifdown optional")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David Ahern <dsahern@gmail.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/addrconf.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -3296,7 +3296,8 @@ static int fixup_permanent_addr(struct i
+                                     idev->dev, 0, 0);
+       }
+-      addrconf_dad_start(ifp);
++      if (ifp->state == INET6_IFADDR_STATE_PREDAD)
++              addrconf_dad_start(ifp);
+       return 0;
+ }
+@@ -3651,7 +3652,7 @@ restart:
+               if (keep) {
+                       /* set state to skip the notifier below */
+                       state = INET6_IFADDR_STATE_DEAD;
+-                      ifa->state = 0;
++                      ifa->state = INET6_IFADDR_STATE_PREDAD;
+                       if (!(ifa->flags & IFA_F_NODAD))
+                               ifa->flags |= IFA_F_TENTATIVE;
diff --git a/queue-4.11/net-macb-fix-phy-interrupt-parsing.patch b/queue-4.11/net-macb-fix-phy-interrupt-parsing.patch
new file mode 100644 (file)
index 0000000..4303d6c
--- /dev/null
@@ -0,0 +1,51 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Date: Wed, 26 Apr 2017 12:06:28 +0200
+Subject: net: macb: fix phy interrupt parsing
+
+From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+
+
+[ Upstream commit ae3696c167cc04d32634c4af82f43b446c5176b0 ]
+
+Since 83a77e9ec415, the phydev irq is explicitly set to PHY_POLL when
+there is no pdata. It doesn't work on DT enabled platforms because the
+phydev irq is already set by libphy before.
+
+Fixes: 83a77e9ec415 ("net: macb: Added PCI wrapper for Platform Driver.")
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/cadence/macb.c |   18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/ethernet/cadence/macb.c
++++ b/drivers/net/ethernet/cadence/macb.c
+@@ -432,15 +432,17 @@ static int macb_mii_probe(struct net_dev
+       }
+       pdata = dev_get_platdata(&bp->pdev->dev);
+-      if (pdata && gpio_is_valid(pdata->phy_irq_pin)) {
+-              ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin,
+-                                      "phy int");
+-              if (!ret) {
+-                      phy_irq = gpio_to_irq(pdata->phy_irq_pin);
+-                      phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
++      if (pdata) {
++              if (gpio_is_valid(pdata->phy_irq_pin)) {
++                      ret = devm_gpio_request(&bp->pdev->dev,
++                                              pdata->phy_irq_pin, "phy int");
++                      if (!ret) {
++                              phy_irq = gpio_to_irq(pdata->phy_irq_pin);
++                              phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
++                      }
++              } else {
++                      phydev->irq = PHY_POLL;
+               }
+-      } else {
+-              phydev->irq = PHY_POLL;
+       }
+       /* attach the mac to the phy */
diff --git a/queue-4.11/net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch b/queue-4.11/net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch
new file mode 100644 (file)
index 0000000..22488c1
--- /dev/null
@@ -0,0 +1,44 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Jon Mason <jon.mason@broadcom.com>
+Date: Mon, 8 May 2017 17:48:35 -0400
+Subject: net: mdio-mux: bcm-iproc: call mdiobus_free() in error path
+
+From: Jon Mason <jon.mason@broadcom.com>
+
+
+[ Upstream commit 922c60e89d52730050c6ccca218bff40cc8bcd8e ]
+
+If an error is encountered in mdio_mux_init(), the error path will call
+mdiobus_free().  Since mdiobus_register() has been called prior to
+mdio_mux_init(), the bus->state will not be MDIOBUS_UNREGISTERED.  This
+causes a BUG_ON() in mdiobus_free().  To correct this issue, add an
+error path for mdio_mux_init() which calls mdiobus_unregister() prior to
+mdiobus_free().
+
+Signed-off-by: Jon Mason <jon.mason@broadcom.com>
+Fixes: 98bc865a1ec8 ("net: mdio-mux: Add MDIO mux driver for iProc SoCs")
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/mdio-mux-bcm-iproc.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/mdio-mux-bcm-iproc.c
++++ b/drivers/net/phy/mdio-mux-bcm-iproc.c
+@@ -203,11 +203,14 @@ static int mdio_mux_iproc_probe(struct p
+                          &md->mux_handle, md, md->mii_bus);
+       if (rc) {
+               dev_info(md->dev, "mdiomux initialization failed\n");
+-              goto out;
++              goto out_register;
+       }
+       dev_info(md->dev, "iProc mdiomux registered\n");
+       return 0;
++
++out_register:
++      mdiobus_unregister(bus);
+ out:
+       mdiobus_free(bus);
+       return rc;
diff --git a/queue-4.11/net-usb-qmi_wwan-add-telit-me910-support.patch b/queue-4.11/net-usb-qmi_wwan-add-telit-me910-support.patch
new file mode 100644 (file)
index 0000000..4c1b7b3
--- /dev/null
@@ -0,0 +1,30 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Daniele Palmas <dnlplm@gmail.com>
+Date: Wed, 3 May 2017 10:30:11 +0200
+Subject: net: usb: qmi_wwan: add Telit ME910 support
+
+From: Daniele Palmas <dnlplm@gmail.com>
+
+
+[ Upstream commit 4c54dc0277d0d55a9248c43aebd31858f926a056 ]
+
+This patch adds support for Telit ME910 PID 0x1100.
+
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/qmi_wwan.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -907,6 +907,7 @@ static const struct usb_device_id produc
+       {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
+       {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
++      {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
+       {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */
+       {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},    /* XS Stick W100-2 from 4G Systems */
diff --git a/queue-4.11/rtnetlink-nul-terminate-ifla_phys_port_name-string.patch b/queue-4.11/rtnetlink-nul-terminate-ifla_phys_port_name-string.patch
new file mode 100644 (file)
index 0000000..423c12a
--- /dev/null
@@ -0,0 +1,37 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Michal Schmidt <mschmidt@redhat.com>
+Date: Thu, 4 May 2017 16:48:58 +0200
+Subject: rtnetlink: NUL-terminate IFLA_PHYS_PORT_NAME string
+
+From: Michal Schmidt <mschmidt@redhat.com>
+
+
+[ Upstream commit 77ef033b687c3e030017c94a29bf6ea3aaaef678 ]
+
+IFLA_PHYS_PORT_NAME is a string attribute, so terminate it with \0.
+Otherwise libnl3 fails to validate netlink messages with this attribute.
+"ip -detail a" assumes too that the attribute is NUL-terminated when
+printing it. It often was, due to padding.
+
+I noticed this as libvirtd failing to start on a system with sfc driver
+after upgrading it to Linux 4.11, i.e. when sfc added support for
+phys_port_name.
+
+Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/rtnetlink.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -1056,7 +1056,7 @@ static int rtnl_phys_port_name_fill(stru
+               return err;
+       }
+-      if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name))
++      if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name))
+               return -EMSGSIZE;
+       return 0;
index 69496b9f04cd222da886de065ca69d8552e27872..61c82b39ffadcba2b578dac925de03056c2b6160 100644 (file)
@@ -5,3 +5,20 @@ brcmfmac-ensure-pointer-correctly-set-if-skb-data-location-changes.patch
 brcmfmac-make-skb-header-writable-before-use.patch
 sparc64-fix-fault-handling-in-ngbzero.s-and-genbzero.s.patch
 refcount-change-export_symbol-markings.patch
+net-macb-fix-phy-interrupt-parsing.patch
+tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch
+geneve-fix-incorrect-setting-of-udp-checksum-flag.patch
+bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch
+bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch
+tcp-fix-wraparound-issue-in-tcp_lp.patch
+net-ipv6-do-not-duplicate-dad-on-link-up.patch
+net-usb-qmi_wwan-add-telit-me910-support.patch
+tcp-do-not-inherit-fastopen_req-from-parent.patch
+ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch
+rtnetlink-nul-terminate-ifla_phys_port_name-string.patch
+ipv6-initialize-route-null-entry-in-addrconf_init.patch
+ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch
+tcp-randomize-timestamps-on-syncookies.patch
+bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch
+bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch
+net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch
diff --git a/queue-4.11/tcp-do-not-inherit-fastopen_req-from-parent.patch b/queue-4.11/tcp-do-not-inherit-fastopen_req-from-parent.patch
new file mode 100644 (file)
index 0000000..a9cc164
--- /dev/null
@@ -0,0 +1,149 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 3 May 2017 06:39:31 -0700
+Subject: tcp: do not inherit fastopen_req from parent
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 8b485ce69876c65db12ed390e7f9c0d2a64eff2c ]
+
+Under fuzzer stress, it is possible that a child gets a non NULL
+fastopen_req pointer from its parent at accept() time, when/if parent
+morphs from listener to active session.
+
+We need to make sure this can not happen, by clearing the field after
+socket cloning.
+
+BUG: Double free or freeing an invalid pointer
+Unexpected shadow byte: 0xFB
+CPU: 3 PID: 20933 Comm: syz-executor3 Not tainted 4.11.0+ #306
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
+01/01/2011
+Call Trace:
+ <IRQ>
+ __dump_stack lib/dump_stack.c:16 [inline]
+ dump_stack+0x292/0x395 lib/dump_stack.c:52
+ kasan_object_err+0x1c/0x70 mm/kasan/report.c:164
+ kasan_report_double_free+0x5c/0x70 mm/kasan/report.c:185
+ kasan_slab_free+0x9d/0xc0 mm/kasan/kasan.c:580
+ slab_free_hook mm/slub.c:1357 [inline]
+ slab_free_freelist_hook mm/slub.c:1379 [inline]
+ slab_free mm/slub.c:2961 [inline]
+ kfree+0xe8/0x2b0 mm/slub.c:3882
+ tcp_free_fastopen_req net/ipv4/tcp.c:1077 [inline]
+ tcp_disconnect+0xc15/0x13e0 net/ipv4/tcp.c:2328
+ inet_child_forget+0xb8/0x600 net/ipv4/inet_connection_sock.c:898
+ inet_csk_reqsk_queue_add+0x1e7/0x250
+net/ipv4/inet_connection_sock.c:928
+ tcp_get_cookie_sock+0x21a/0x510 net/ipv4/syncookies.c:217
+ cookie_v4_check+0x1a19/0x28b0 net/ipv4/syncookies.c:384
+ tcp_v4_cookie_check net/ipv4/tcp_ipv4.c:1384 [inline]
+ tcp_v4_do_rcv+0x731/0x940 net/ipv4/tcp_ipv4.c:1421
+ tcp_v4_rcv+0x2dc0/0x31c0 net/ipv4/tcp_ipv4.c:1715
+ ip_local_deliver_finish+0x4cc/0xc20 net/ipv4/ip_input.c:216
+ NF_HOOK include/linux/netfilter.h:257 [inline]
+ ip_local_deliver+0x1ce/0x700 net/ipv4/ip_input.c:257
+ dst_input include/net/dst.h:492 [inline]
+ ip_rcv_finish+0xb1d/0x20b0 net/ipv4/ip_input.c:396
+ NF_HOOK include/linux/netfilter.h:257 [inline]
+ ip_rcv+0xd8c/0x19c0 net/ipv4/ip_input.c:487
+ __netif_receive_skb_core+0x1ad1/0x3400 net/core/dev.c:4210
+ __netif_receive_skb+0x2a/0x1a0 net/core/dev.c:4248
+ process_backlog+0xe5/0x6c0 net/core/dev.c:4868
+ napi_poll net/core/dev.c:5270 [inline]
+ net_rx_action+0xe70/0x18e0 net/core/dev.c:5335
+ __do_softirq+0x2fb/0xb99 kernel/softirq.c:284
+ do_softirq_own_stack+0x1c/0x30 arch/x86/entry/entry_64.S:899
+ </IRQ>
+ do_softirq.part.17+0x1e8/0x230 kernel/softirq.c:328
+ do_softirq kernel/softirq.c:176 [inline]
+ __local_bh_enable_ip+0x1cf/0x1e0 kernel/softirq.c:181
+ local_bh_enable include/linux/bottom_half.h:31 [inline]
+ rcu_read_unlock_bh include/linux/rcupdate.h:931 [inline]
+ ip_finish_output2+0x9ab/0x15e0 net/ipv4/ip_output.c:230
+ ip_finish_output+0xa35/0xdf0 net/ipv4/ip_output.c:316
+ NF_HOOK_COND include/linux/netfilter.h:246 [inline]
+ ip_output+0x1f6/0x7b0 net/ipv4/ip_output.c:404
+ dst_output include/net/dst.h:486 [inline]
+ ip_local_out+0x95/0x160 net/ipv4/ip_output.c:124
+ ip_queue_xmit+0x9a8/0x1a10 net/ipv4/ip_output.c:503
+ tcp_transmit_skb+0x1ade/0x3470 net/ipv4/tcp_output.c:1057
+ tcp_write_xmit+0x79e/0x55b0 net/ipv4/tcp_output.c:2265
+ __tcp_push_pending_frames+0xfa/0x3a0 net/ipv4/tcp_output.c:2450
+ tcp_push+0x4ee/0x780 net/ipv4/tcp.c:683
+ tcp_sendmsg+0x128d/0x39b0 net/ipv4/tcp.c:1342
+ inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762
+ sock_sendmsg_nosec net/socket.c:633 [inline]
+ sock_sendmsg+0xca/0x110 net/socket.c:643
+ SYSC_sendto+0x660/0x810 net/socket.c:1696
+ SyS_sendto+0x40/0x50 net/socket.c:1664
+ entry_SYSCALL_64_fastpath+0x1f/0xbe
+RIP: 0033:0x446059
+RSP: 002b:00007faa6761fb58 EFLAGS: 00000282 ORIG_RAX: 000000000000002c
+RAX: ffffffffffffffda RBX: 0000000000000017 RCX: 0000000000446059
+RDX: 0000000000000001 RSI: 0000000020ba3fcd RDI: 0000000000000017
+RBP: 00000000006e40a0 R08: 0000000020ba4ff0 R09: 0000000000000010
+R10: 0000000020000000 R11: 0000000000000282 R12: 0000000000708150
+R13: 0000000000000000 R14: 00007faa676209c0 R15: 00007faa67620700
+Object at ffff88003b5bbcb8, in cache kmalloc-64 size: 64
+Allocated:
+PID = 20909
+ save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
+ save_stack+0x43/0xd0 mm/kasan/kasan.c:513
+ set_track mm/kasan/kasan.c:525 [inline]
+ kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:616
+ kmem_cache_alloc_trace+0x82/0x270 mm/slub.c:2745
+ kmalloc include/linux/slab.h:490 [inline]
+ kzalloc include/linux/slab.h:663 [inline]
+ tcp_sendmsg_fastopen net/ipv4/tcp.c:1094 [inline]
+ tcp_sendmsg+0x221a/0x39b0 net/ipv4/tcp.c:1139
+ inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762
+ sock_sendmsg_nosec net/socket.c:633 [inline]
+ sock_sendmsg+0xca/0x110 net/socket.c:643
+ SYSC_sendto+0x660/0x810 net/socket.c:1696
+ SyS_sendto+0x40/0x50 net/socket.c:1664
+ entry_SYSCALL_64_fastpath+0x1f/0xbe
+Freed:
+PID = 20909
+ save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
+ save_stack+0x43/0xd0 mm/kasan/kasan.c:513
+ set_track mm/kasan/kasan.c:525 [inline]
+ kasan_slab_free+0x73/0xc0 mm/kasan/kasan.c:589
+ slab_free_hook mm/slub.c:1357 [inline]
+ slab_free_freelist_hook mm/slub.c:1379 [inline]
+ slab_free mm/slub.c:2961 [inline]
+ kfree+0xe8/0x2b0 mm/slub.c:3882
+ tcp_free_fastopen_req net/ipv4/tcp.c:1077 [inline]
+ tcp_disconnect+0xc15/0x13e0 net/ipv4/tcp.c:2328
+ __inet_stream_connect+0x20c/0xf90 net/ipv4/af_inet.c:593
+ tcp_sendmsg_fastopen net/ipv4/tcp.c:1111 [inline]
+ tcp_sendmsg+0x23a8/0x39b0 net/ipv4/tcp.c:1139
+ inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762
+ sock_sendmsg_nosec net/socket.c:633 [inline]
+ sock_sendmsg+0xca/0x110 net/socket.c:643
+ SYSC_sendto+0x660/0x810 net/socket.c:1696
+ SyS_sendto+0x40/0x50 net/socket.c:1664
+ entry_SYSCALL_64_fastpath+0x1f/0xbe
+
+Fixes: e994b2f0fb92 ("tcp: do not lock listener to process SYN packets")
+Fixes: 7db92362d2fe ("tcp: fix potential double free issue for fastopen_req")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Acked-by: Wei Wang <weiwan@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_minisocks.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -536,6 +536,7 @@ struct sock *tcp_create_openreq_child(co
+                       newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
+               newtp->rx_opt.mss_clamp = req->mss;
+               tcp_ecn_openreq_child(newtp, req);
++              newtp->fastopen_req = NULL;
+               newtp->fastopen_rsk = NULL;
+               newtp->syn_data_acked = 0;
+               newtp->rack.mstamp.v64 = 0;
diff --git a/queue-4.11/tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch b/queue-4.11/tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch
new file mode 100644 (file)
index 0000000..15b305c
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Davide Caratti <dcaratti@redhat.com>
+Date: Wed, 26 Apr 2017 19:07:35 +0200
+Subject: tcp: fix access to sk->sk_state in tcp_poll()
+
+From: Davide Caratti <dcaratti@redhat.com>
+
+
+[ Upstream commit d68be71ea14d609a5f31534003319be5db422595 ]
+
+avoid direct access to sk->sk_state when tcp_poll() is called on a socket
+using active TCP fastopen with deferred connect. Use local variable
+'state', which stores the result of sk_state_load(), like it was done in
+commit 00fd38d938db ("tcp: ensure proper barriers in lockless contexts").
+
+Fixes: 19f6d3f3c842 ("net/tcp-fastopen: Add new API support")
+Signed-off-by: Davide Caratti <dcaratti@redhat.com>
+Acked-by: Wei Wang <weiwan@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -533,7 +533,7 @@ unsigned int tcp_poll(struct file *file,
+               if (tp->urg_data & TCP_URG_VALID)
+                       mask |= POLLPRI;
+-      } else if (sk->sk_state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
++      } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
+               /* Active TCP fastopen socket with defer_connect
+                * Return POLLOUT so application can call write()
+                * in order for kernel to generate SYN+data
diff --git a/queue-4.11/tcp-fix-wraparound-issue-in-tcp_lp.patch b/queue-4.11/tcp-fix-wraparound-issue-in-tcp_lp.patch
new file mode 100644 (file)
index 0000000..3ff0b51
--- /dev/null
@@ -0,0 +1,41 @@
+From foo@baz Thu May 11 11:03:14 CEST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 1 May 2017 15:29:48 -0700
+Subject: tcp: fix wraparound issue in tcp_lp
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit a9f11f963a546fea9144f6a6d1a307e814a387e7 ]
+
+Be careful when comparing tcp_time_stamp to some u32 quantity,
+otherwise result can be surprising.
+
+Fixes: 7c106d7e782b ("[TCP]: TCP Low Priority congestion control")
+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>
+---
+ net/ipv4/tcp_lp.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_lp.c
++++ b/net/ipv4/tcp_lp.c
+@@ -264,13 +264,15 @@ static void tcp_lp_pkts_acked(struct soc
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
++      u32 delta;
+       if (sample->rtt_us > 0)
+               tcp_lp_rtt_sample(sk, sample->rtt_us);
+       /* calc inference */
+-      if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
+-              lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
++      delta = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
++      if ((s32)delta > 0)
++              lp->inference = 3 * delta;
+       /* test if within inference */
+       if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
diff --git a/queue-4.11/tcp-randomize-timestamps-on-syncookies.patch b/queue-4.11/tcp-randomize-timestamps-on-syncookies.patch
new file mode 100644 (file)
index 0000000..e3eab8e
--- /dev/null
@@ -0,0 +1,447 @@
+From foo@baz Thu May 11 11:03:15 CEST 2017
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 5 May 2017 06:56:54 -0700
+Subject: tcp: randomize timestamps on syncookies
+
+From: Eric Dumazet <edumazet@google.com>
+
+
+[ Upstream commit 84b114b98452c431299d99c135f751659e517acb ]
+
+Whole point of randomization was to hide server uptime, but an attacker
+can simply start a syn flood and TCP generates 'old style' timestamps,
+directly revealing server jiffies value.
+
+Also, TSval sent by the server to a particular remote address vary
+depending on syncookies being sent or not, potentially triggering PAWS
+drops for innocent clients.
+
+Lets implement proper randomization, including for SYNcookies.
+
+Also we do not need to export sysctl_tcp_timestamps, since it is not
+used from a module.
+
+In v2, I added Florian feedback and contribution, adding tsoff to
+tcp_get_cookie_sock().
+
+v3 removed one unused variable in tcp_v4_connect() as Florian spotted.
+
+Fixes: 95a22caee396c ("tcp: randomize tcp timestamp offsets for each connection")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Tested-by: Florian Westphal <fw@strlen.de>
+Cc: Yuchung Cheng <ycheng@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/secure_seq.h |   10 ++++++----
+ include/net/tcp.h        |    5 +++--
+ net/core/secure_seq.c    |   34 ++++++++++++++++++++--------------
+ net/ipv4/syncookies.c    |   12 ++++++++++--
+ net/ipv4/tcp_input.c     |    8 +++-----
+ net/ipv4/tcp_ipv4.c      |   32 +++++++++++++++++++-------------
+ net/ipv6/syncookies.c    |   10 +++++++++-
+ net/ipv6/tcp_ipv6.c      |   32 +++++++++++++++++++-------------
+ 8 files changed, 89 insertions(+), 54 deletions(-)
+
+--- a/include/net/secure_seq.h
++++ b/include/net/secure_seq.h
+@@ -6,10 +6,12 @@
+ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                              __be16 dport);
+-u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+-                             __be16 sport, __be16 dport, u32 *tsoff);
+-u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+-                               __be16 sport, __be16 dport, u32 *tsoff);
++u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
++                 __be16 sport, __be16 dport);
++u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr);
++u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
++                   __be16 sport, __be16 dport);
++u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr);
+ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+                               __be16 sport, __be16 dport);
+ u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -471,7 +471,7 @@ void inet_sk_rx_dst_set(struct sock *sk,
+ /* From syncookies.c */
+ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+                                struct request_sock *req,
+-                               struct dst_entry *dst);
++                               struct dst_entry *dst, u32 tsoff);
+ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
+                     u32 cookie);
+ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb);
+@@ -1816,7 +1816,8 @@ struct tcp_request_sock_ops {
+       struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
+                                      const struct request_sock *req,
+                                      bool *strict);
+-      __u32 (*init_seq)(const struct sk_buff *skb, u32 *tsoff);
++      u32 (*init_seq)(const struct sk_buff *skb);
++      u32 (*init_ts_off)(const struct sk_buff *skb);
+       int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
+                          struct flowi *fl, struct request_sock *req,
+                          struct tcp_fastopen_cookie *foc,
+--- a/net/core/secure_seq.c
++++ b/net/core/secure_seq.c
+@@ -24,9 +24,13 @@ static siphash_key_t ts_secret __read_mo
+ static __always_inline void net_secret_init(void)
+ {
+-      net_get_random_once(&ts_secret, sizeof(ts_secret));
+       net_get_random_once(&net_secret, sizeof(net_secret));
+ }
++
++static __always_inline void ts_secret_init(void)
++{
++      net_get_random_once(&ts_secret, sizeof(ts_secret));
++}
+ #endif
+ #ifdef CONFIG_INET
+@@ -47,7 +51,7 @@ static u32 seq_scale(u32 seq)
+ #endif
+ #if IS_ENABLED(CONFIG_IPV6)
+-static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
++u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
+ {
+       const struct {
+               struct in6_addr saddr;
+@@ -60,12 +64,14 @@ static u32 secure_tcpv6_ts_off(const __b
+       if (sysctl_tcp_timestamps != 1)
+               return 0;
++      ts_secret_init();
+       return siphash(&combined, offsetofend(typeof(combined), daddr),
+                      &ts_secret);
+ }
++EXPORT_SYMBOL(secure_tcpv6_ts_off);
+-u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+-                               __be16 sport, __be16 dport, u32 *tsoff)
++u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
++                   __be16 sport, __be16 dport)
+ {
+       const struct {
+               struct in6_addr saddr;
+@@ -78,14 +84,14 @@ u32 secure_tcpv6_sequence_number(const _
+               .sport = sport,
+               .dport = dport
+       };
+-      u64 hash;
++      u32 hash;
++
+       net_secret_init();
+       hash = siphash(&combined, offsetofend(typeof(combined), dport),
+                      &net_secret);
+-      *tsoff = secure_tcpv6_ts_off(saddr, daddr);
+       return seq_scale(hash);
+ }
+-EXPORT_SYMBOL(secure_tcpv6_sequence_number);
++EXPORT_SYMBOL(secure_tcpv6_seq);
+ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                              __be16 dport)
+@@ -107,30 +113,30 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral
+ #endif
+ #ifdef CONFIG_INET
+-static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
++u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
+ {
+       if (sysctl_tcp_timestamps != 1)
+               return 0;
++      ts_secret_init();
+       return siphash_2u32((__force u32)saddr, (__force u32)daddr,
+                           &ts_secret);
+ }
+-/* secure_tcp_sequence_number(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d),
++/* secure_tcp_seq_and_tsoff(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d),
+  * but fortunately, `sport' cannot be 0 in any circumstances. If this changes,
+  * it would be easy enough to have the former function use siphash_4u32, passing
+  * the arguments as separate u32.
+  */
+-
+-u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+-                             __be16 sport, __be16 dport, u32 *tsoff)
++u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
++                 __be16 sport, __be16 dport)
+ {
+-      u64 hash;
++      u32 hash;
++
+       net_secret_init();
+       hash = siphash_3u32((__force u32)saddr, (__force u32)daddr,
+                           (__force u32)sport << 16 | (__force u32)dport,
+                           &net_secret);
+-      *tsoff = secure_tcp_ts_off(saddr, daddr);
+       return seq_scale(hash);
+ }
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -16,6 +16,7 @@
+ #include <linux/siphash.h>
+ #include <linux/kernel.h>
+ #include <linux/export.h>
++#include <net/secure_seq.h>
+ #include <net/tcp.h>
+ #include <net/route.h>
+@@ -203,7 +204,7 @@ EXPORT_SYMBOL_GPL(__cookie_v4_check);
+ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+                                struct request_sock *req,
+-                               struct dst_entry *dst)
++                               struct dst_entry *dst, u32 tsoff)
+ {
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct sock *child;
+@@ -213,6 +214,7 @@ struct sock *tcp_get_cookie_sock(struct
+                                                NULL, &own_req);
+       if (child) {
+               atomic_set(&req->rsk_refcnt, 1);
++              tcp_sk(child)->tsoffset = tsoff;
+               sock_rps_save_rxhash(child, skb);
+               inet_csk_reqsk_queue_add(sk, req, child);
+       } else {
+@@ -292,6 +294,7 @@ struct sock *cookie_v4_check(struct sock
+       struct rtable *rt;
+       __u8 rcv_wscale;
+       struct flowi4 fl4;
++      u32 tsoff = 0;
+       if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
+               goto out;
+@@ -311,6 +314,11 @@ struct sock *cookie_v4_check(struct sock
+       memset(&tcp_opt, 0, sizeof(tcp_opt));
+       tcp_parse_options(skb, &tcp_opt, 0, NULL);
++      if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
++              tsoff = secure_tcp_ts_off(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
++              tcp_opt.rcv_tsecr -= tsoff;
++      }
++
+       if (!cookie_timestamp_decode(&tcp_opt))
+               goto out;
+@@ -381,7 +389,7 @@ struct sock *cookie_v4_check(struct sock
+       ireq->rcv_wscale  = rcv_wscale;
+       ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst);
+-      ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst);
++      ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff);
+       /* ip_queue_xmit() depends on our flow being setup
+        * Normal sockets get it right from inet_csk_route_child_sock()
+        */
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -85,7 +85,6 @@ int sysctl_tcp_dsack __read_mostly = 1;
+ int sysctl_tcp_app_win __read_mostly = 31;
+ int sysctl_tcp_adv_win_scale __read_mostly = 1;
+ EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
+-EXPORT_SYMBOL(sysctl_tcp_timestamps);
+ /* rfc5961 challenge ack rate limiting */
+ int sysctl_tcp_challenge_ack_limit = 1000;
+@@ -6332,8 +6331,8 @@ int tcp_conn_request(struct request_sock
+       if (security_inet_conn_request(sk, skb, req))
+               goto drop_and_free;
+-      if (isn && tmp_opt.tstamp_ok)
+-              af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
++      if (tmp_opt.tstamp_ok)
++              tcp_rsk(req)->ts_off = af_ops->init_ts_off(skb);
+       if (!want_cookie && !isn) {
+               /* VJ's idea. We save last timestamp seen
+@@ -6375,7 +6374,7 @@ int tcp_conn_request(struct request_sock
+                       goto drop_and_release;
+               }
+-              isn = af_ops->init_seq(skb, &tcp_rsk(req)->ts_off);
++              isn = af_ops->init_seq(skb);
+       }
+       if (!dst) {
+               dst = af_ops->route_req(sk, &fl, req, NULL);
+@@ -6387,7 +6386,6 @@ int tcp_conn_request(struct request_sock
+       if (want_cookie) {
+               isn = cookie_init_sequence(af_ops, sk, skb, &req->mss);
+-              tcp_rsk(req)->ts_off = 0;
+               req->cookie_ts = tmp_opt.tstamp_ok;
+               if (!tmp_opt.tstamp_ok)
+                       inet_rsk(req)->ecn_ok = 0;
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -94,12 +94,18 @@ static int tcp_v4_md5_hash_hdr(char *md5
+ struct inet_hashinfo tcp_hashinfo;
+ EXPORT_SYMBOL(tcp_hashinfo);
+-static u32 tcp_v4_init_sequence(const struct sk_buff *skb, u32 *tsoff)
++static u32 tcp_v4_init_seq(const struct sk_buff *skb)
+ {
+-      return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
+-                                        ip_hdr(skb)->saddr,
+-                                        tcp_hdr(skb)->dest,
+-                                        tcp_hdr(skb)->source, tsoff);
++      return secure_tcp_seq(ip_hdr(skb)->daddr,
++                            ip_hdr(skb)->saddr,
++                            tcp_hdr(skb)->dest,
++                            tcp_hdr(skb)->source);
++}
++
++static u32 tcp_v4_init_ts_off(const struct sk_buff *skb)
++{
++      return secure_tcp_ts_off(ip_hdr(skb)->daddr,
++                               ip_hdr(skb)->saddr);
+ }
+ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+@@ -145,7 +151,6 @@ int tcp_v4_connect(struct sock *sk, stru
+       struct flowi4 *fl4;
+       struct rtable *rt;
+       int err;
+-      u32 seq;
+       struct ip_options_rcu *inet_opt;
+       struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
+@@ -236,13 +241,13 @@ int tcp_v4_connect(struct sock *sk, stru
+       rt = NULL;
+       if (likely(!tp->repair)) {
+-              seq = secure_tcp_sequence_number(inet->inet_saddr,
+-                                               inet->inet_daddr,
+-                                               inet->inet_sport,
+-                                               usin->sin_port,
+-                                               &tp->tsoffset);
+               if (!tp->write_seq)
+-                      tp->write_seq = seq;
++                      tp->write_seq = secure_tcp_seq(inet->inet_saddr,
++                                                     inet->inet_daddr,
++                                                     inet->inet_sport,
++                                                     usin->sin_port);
++              tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr,
++                                               inet->inet_daddr);
+       }
+       inet->inet_id = tp->write_seq ^ jiffies;
+@@ -1253,7 +1258,8 @@ static const struct tcp_request_sock_ops
+       .cookie_init_seq =      cookie_v4_init_sequence,
+ #endif
+       .route_req      =       tcp_v4_route_req,
+-      .init_seq       =       tcp_v4_init_sequence,
++      .init_seq       =       tcp_v4_init_seq,
++      .init_ts_off    =       tcp_v4_init_ts_off,
+       .send_synack    =       tcp_v4_send_synack,
+ };
+--- a/net/ipv6/syncookies.c
++++ b/net/ipv6/syncookies.c
+@@ -18,6 +18,7 @@
+ #include <linux/random.h>
+ #include <linux/siphash.h>
+ #include <linux/kernel.h>
++#include <net/secure_seq.h>
+ #include <net/ipv6.h>
+ #include <net/tcp.h>
+@@ -143,6 +144,7 @@ struct sock *cookie_v6_check(struct sock
+       int mss;
+       struct dst_entry *dst;
+       __u8 rcv_wscale;
++      u32 tsoff = 0;
+       if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
+               goto out;
+@@ -162,6 +164,12 @@ struct sock *cookie_v6_check(struct sock
+       memset(&tcp_opt, 0, sizeof(tcp_opt));
+       tcp_parse_options(skb, &tcp_opt, 0, NULL);
++      if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
++              tsoff = secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
++                                          ipv6_hdr(skb)->saddr.s6_addr32);
++              tcp_opt.rcv_tsecr -= tsoff;
++      }
++
+       if (!cookie_timestamp_decode(&tcp_opt))
+               goto out;
+@@ -242,7 +250,7 @@ struct sock *cookie_v6_check(struct sock
+       ireq->rcv_wscale = rcv_wscale;
+       ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst);
+-      ret = tcp_get_cookie_sock(sk, skb, req, dst);
++      ret = tcp_get_cookie_sock(sk, skb, req, dst, tsoff);
+ out:
+       return ret;
+ out_free:
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -101,12 +101,18 @@ static void inet6_sk_rx_dst_set(struct s
+       }
+ }
+-static u32 tcp_v6_init_sequence(const struct sk_buff *skb, u32 *tsoff)
++static u32 tcp_v6_init_seq(const struct sk_buff *skb)
+ {
+-      return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
+-                                          ipv6_hdr(skb)->saddr.s6_addr32,
+-                                          tcp_hdr(skb)->dest,
+-                                          tcp_hdr(skb)->source, tsoff);
++      return secure_tcpv6_seq(ipv6_hdr(skb)->daddr.s6_addr32,
++                              ipv6_hdr(skb)->saddr.s6_addr32,
++                              tcp_hdr(skb)->dest,
++                              tcp_hdr(skb)->source);
++}
++
++static u32 tcp_v6_init_ts_off(const struct sk_buff *skb)
++{
++      return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
++                                 ipv6_hdr(skb)->saddr.s6_addr32);
+ }
+ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
+@@ -122,7 +128,6 @@ static int tcp_v6_connect(struct sock *s
+       struct flowi6 fl6;
+       struct dst_entry *dst;
+       int addr_type;
+-      u32 seq;
+       int err;
+       struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
+@@ -287,13 +292,13 @@ static int tcp_v6_connect(struct sock *s
+       sk_set_txhash(sk);
+       if (likely(!tp->repair)) {
+-              seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
+-                                                 sk->sk_v6_daddr.s6_addr32,
+-                                                 inet->inet_sport,
+-                                                 inet->inet_dport,
+-                                                 &tp->tsoffset);
+               if (!tp->write_seq)
+-                      tp->write_seq = seq;
++                      tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32,
++                                                       sk->sk_v6_daddr.s6_addr32,
++                                                       inet->inet_sport,
++                                                       inet->inet_dport);
++              tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32,
++                                                 sk->sk_v6_daddr.s6_addr32);
+       }
+       if (tcp_fastopen_defer_connect(sk, &err))
+@@ -757,7 +762,8 @@ static const struct tcp_request_sock_ops
+       .cookie_init_seq =      cookie_v6_init_sequence,
+ #endif
+       .route_req      =       tcp_v6_route_req,
+-      .init_seq       =       tcp_v6_init_sequence,
++      .init_seq       =       tcp_v6_init_seq,
++      .init_ts_off    =       tcp_v6_init_ts_off,
+       .send_synack    =       tcp_v6_send_synack,
+ };