From: Greg Kroah-Hartman Date: Thu, 11 May 2017 09:13:20 +0000 (+0200) Subject: 4.11-stable patches X-Git-Tag: v4.4.68~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=665b693fc4366c32cf78cc7a9b9fb282b627bdf5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.11-stable patches 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 --- 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 index 00000000000..29e4ab71e95 --- /dev/null +++ b/queue-4.11/bnxt_en-allocate-enough-space-for-ntp_fltr_bmap.patch @@ -0,0 +1,34 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Dan Carpenter +Date: Sat, 6 May 2017 03:49:01 +0300 +Subject: bnxt_en: allocate enough space for ->ntp_fltr_bmap + +From: Dan Carpenter + + +[ 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 +Acked-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..eca3696950d --- /dev/null +++ b/queue-4.11/bpf-arm64-fix-jit-branch-offset-related-to-ldimm64.patch @@ -0,0 +1,144 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Daniel Borkmann +Date: Tue, 2 May 2017 20:34:54 +0200 +Subject: bpf, arm64: fix jit branch offset related to ldimm64 + +From: Daniel Borkmann + + +[ 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 +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Cc: Xi Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..f7b9e4a5b02 --- /dev/null +++ b/queue-4.11/bpf-don-t-let-ldimm64-leak-map-addresses-on-unprivileged.patch @@ -0,0 +1,79 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Daniel Borkmann +Date: Mon, 8 May 2017 00:04:09 +0200 +Subject: bpf: don't let ldimm64 leak map addresses on unprivileged + +From: Daniel Borkmann + + +[ 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 +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b0575dd0e7d --- /dev/null +++ b/queue-4.11/bpf-enhance-verifier-to-understand-stack-pointer-arithmetic.patch @@ -0,0 +1,91 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Yonghong Song +Date: Sat, 29 Apr 2017 22:52:42 -0700 +Subject: bpf: enhance verifier to understand stack pointer arithmetic + +From: Yonghong Song + + +[ 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 +Acked-by: Martin KaFai Lau +Acked-by: Daniel Borkmann +Signed-off-by: Alexei Starovoitov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a97b63b4900 --- /dev/null +++ b/queue-4.11/geneve-fix-incorrect-setting-of-udp-checksum-flag.patch @@ -0,0 +1,42 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Girish Moodalbail +Date: Thu, 27 Apr 2017 14:11:53 -0700 +Subject: geneve: fix incorrect setting of UDP checksum flag + +From: Girish Moodalbail + + +[ 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: 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 +Acked-by: Pravin B Shelar +Acked-by: Lance Richardson +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2298a7fa995 --- /dev/null +++ b/queue-4.11/ipv4-ipv6-ensure-raw-socket-message-is-big-enough-to-hold-an-ip-header.patch @@ -0,0 +1,112 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Alexander Potapenko +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 + + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..109eee842f8 --- /dev/null +++ b/queue-4.11/ipv6-initialize-route-null-entry-in-addrconf_init.patch @@ -0,0 +1,97 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: WANG Cong +Date: Wed, 3 May 2017 22:07:31 -0700 +Subject: ipv6: initialize route null entry in addrconf_init() + +From: WANG Cong + + +[ 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 +Signed-off-by: Cong Wang +Tested-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2bca3b0a363 --- /dev/null +++ b/queue-4.11/ipv6-reorder-ip6_route_dev_notifier-after-ipv6_dev_notf.patch @@ -0,0 +1,101 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: WANG Cong +Date: Mon, 8 May 2017 10:12:13 -0700 +Subject: ipv6: reorder ip6_route_dev_notifier after ipv6_dev_notf + +From: WANG Cong + + +[ 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 +Tested-by: David Ahern +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + +--- 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 index 00000000000..3da2e14a1b5 --- /dev/null +++ b/queue-4.11/net-ipv6-do-not-duplicate-dad-on-link-up.patch @@ -0,0 +1,119 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: David Ahern +Date: Tue, 2 May 2017 14:43:44 -0700 +Subject: net: ipv6: Do not duplicate DAD on link up + +From: David Ahern + + +[ 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 +Signed-off-by: David Ahern +Tested-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4303d6c4718 --- /dev/null +++ b/queue-4.11/net-macb-fix-phy-interrupt-parsing.patch @@ -0,0 +1,51 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Alexandre Belloni +Date: Wed, 26 Apr 2017 12:06:28 +0200 +Subject: net: macb: fix phy interrupt parsing + +From: Alexandre Belloni + + +[ 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 +Acked-by: Nicolas Ferre +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..22488c1b488 --- /dev/null +++ b/queue-4.11/net-mdio-mux-bcm-iproc-call-mdiobus_free-in-error-path.patch @@ -0,0 +1,44 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Jon Mason +Date: Mon, 8 May 2017 17:48:35 -0400 +Subject: net: mdio-mux: bcm-iproc: call mdiobus_free() in error path + +From: Jon Mason + + +[ 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 +Fixes: 98bc865a1ec8 ("net: mdio-mux: Add MDIO mux driver for iProc SoCs") +Acked-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4c1b7b393dd --- /dev/null +++ b/queue-4.11/net-usb-qmi_wwan-add-telit-me910-support.patch @@ -0,0 +1,30 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Daniele Palmas +Date: Wed, 3 May 2017 10:30:11 +0200 +Subject: net: usb: qmi_wwan: add Telit ME910 support + +From: Daniele Palmas + + +[ Upstream commit 4c54dc0277d0d55a9248c43aebd31858f926a056 ] + +This patch adds support for Telit ME910 PID 0x1100. + +Signed-off-by: Daniele Palmas +Acked-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..423c12a0659 --- /dev/null +++ b/queue-4.11/rtnetlink-nul-terminate-ifla_phys_port_name-string.patch @@ -0,0 +1,37 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Michal Schmidt +Date: Thu, 4 May 2017 16:48:58 +0200 +Subject: rtnetlink: NUL-terminate IFLA_PHYS_PORT_NAME string + +From: Michal Schmidt + + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-4.11/series b/queue-4.11/series index 69496b9f04c..61c82b39ffa 100644 --- a/queue-4.11/series +++ b/queue-4.11/series @@ -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 index 00000000000..a9cc16417b0 --- /dev/null +++ b/queue-4.11/tcp-do-not-inherit-fastopen_req-from-parent.patch @@ -0,0 +1,149 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Eric Dumazet +Date: Wed, 3 May 2017 06:39:31 -0700 +Subject: tcp: do not inherit fastopen_req from parent + +From: Eric Dumazet + + +[ 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: + + __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 + + 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 +Reported-by: Andrey Konovalov +Acked-by: Wei Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..15b305cadff --- /dev/null +++ b/queue-4.11/tcp-fix-access-to-sk-sk_state-in-tcp_poll.patch @@ -0,0 +1,35 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Davide Caratti +Date: Wed, 26 Apr 2017 19:07:35 +0200 +Subject: tcp: fix access to sk->sk_state in tcp_poll() + +From: Davide Caratti + + +[ 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 +Acked-by: Wei Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3ff0b5184c7 --- /dev/null +++ b/queue-4.11/tcp-fix-wraparound-issue-in-tcp_lp.patch @@ -0,0 +1,41 @@ +From foo@baz Thu May 11 11:03:14 CEST 2017 +From: Eric Dumazet +Date: Mon, 1 May 2017 15:29:48 -0700 +Subject: tcp: fix wraparound issue in tcp_lp + +From: Eric Dumazet + + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..e3eab8ea351 --- /dev/null +++ b/queue-4.11/tcp-randomize-timestamps-on-syncookies.patch @@ -0,0 +1,447 @@ +From foo@baz Thu May 11 11:03:15 CEST 2017 +From: Eric Dumazet +Date: Fri, 5 May 2017 06:56:54 -0700 +Subject: tcp: randomize timestamps on syncookies + +From: Eric Dumazet + + +[ 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 +Reviewed-by: Florian Westphal +Tested-by: Florian Westphal +Cc: Yuchung Cheng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + +@@ -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 + #include + #include ++#include + #include + #include + +@@ -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, + }; +