--- /dev/null
+From a6da0024ffc19e0d47712bb5ca4fd083f76b07df Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Sun, 5 Nov 2017 09:16:09 -0700
+Subject: blktrace: fix unlocked registration of tracepoints
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit a6da0024ffc19e0d47712bb5ca4fd083f76b07df upstream.
+
+We need to ensure that tracepoints are registered and unregistered
+with the users of them. The existing atomic count isn't enough for
+that. Add a lock around the tracepoints, so we serialize access
+to them.
+
+This fixes cases where we have multiple users setting up and
+tearing down tracepoints, like this:
+
+CPU: 0 PID: 2995 Comm: syzkaller857118 Not tainted
+4.14.0-rc5-next-20171018+ #36
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
+Google 01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:16 [inline]
+ dump_stack+0x194/0x257 lib/dump_stack.c:52
+ panic+0x1e4/0x41c kernel/panic.c:183
+ __warn+0x1c4/0x1e0 kernel/panic.c:546
+ report_bug+0x211/0x2d0 lib/bug.c:183
+ fixup_bug+0x40/0x90 arch/x86/kernel/traps.c:177
+ do_trap_no_signal arch/x86/kernel/traps.c:211 [inline]
+ do_trap+0x260/0x390 arch/x86/kernel/traps.c:260
+ do_error_trap+0x120/0x390 arch/x86/kernel/traps.c:297
+ do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:310
+ invalid_op+0x18/0x20 arch/x86/entry/entry_64.S:905
+RIP: 0010:tracepoint_add_func kernel/tracepoint.c:210 [inline]
+RIP: 0010:tracepoint_probe_register_prio+0x397/0x9a0 kernel/tracepoint.c:283
+RSP: 0018:ffff8801d1d1f6c0 EFLAGS: 00010293
+RAX: ffff8801d22e8540 RBX: 00000000ffffffef RCX: ffffffff81710f07
+RDX: 0000000000000000 RSI: ffffffff85b679c0 RDI: ffff8801d5f19818
+RBP: ffff8801d1d1f7c8 R08: ffffffff81710c10 R09: 0000000000000004
+R10: ffff8801d1d1f6b0 R11: 0000000000000003 R12: ffffffff817597f0
+R13: 0000000000000000 R14: 00000000ffffffff R15: ffff8801d1d1f7a0
+ tracepoint_probe_register+0x2a/0x40 kernel/tracepoint.c:304
+ register_trace_block_rq_insert include/trace/events/block.h:191 [inline]
+ blk_register_tracepoints+0x1e/0x2f0 kernel/trace/blktrace.c:1043
+ do_blk_trace_setup+0xa10/0xcf0 kernel/trace/blktrace.c:542
+ blk_trace_setup+0xbd/0x180 kernel/trace/blktrace.c:564
+ sg_ioctl+0xc71/0x2d90 drivers/scsi/sg.c:1089
+ vfs_ioctl fs/ioctl.c:45 [inline]
+ do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:685
+ SYSC_ioctl fs/ioctl.c:700 [inline]
+ SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691
+ entry_SYSCALL_64_fastpath+0x1f/0xbe
+RIP: 0033:0x444339
+RSP: 002b:00007ffe05bb5b18 EFLAGS: 00000206 ORIG_RAX: 0000000000000010
+RAX: ffffffffffffffda RBX: 00000000006d66c0 RCX: 0000000000444339
+RDX: 000000002084cf90 RSI: 00000000c0481273 RDI: 0000000000000009
+RBP: 0000000000000082 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000206 R12: ffffffffffffffff
+R13: 00000000c0481273 R14: 0000000000000000 R15: 0000000000000000
+
+since we can now run these in parallel. Ensure that the exported helpers
+for doing this are grabbing the queue trace mutex.
+
+Reported-by: Steven Rostedt <rostedt@goodmis.org>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/trace/blktrace.c | 32 ++++++++++++++++++++++----------
+ 1 file changed, 22 insertions(+), 10 deletions(-)
+
+--- a/kernel/trace/blktrace.c
++++ b/kernel/trace/blktrace.c
+@@ -57,7 +57,8 @@ static struct tracer_flags blk_tracer_fl
+ };
+
+ /* Global reference count of probes */
+-static atomic_t blk_probes_ref = ATOMIC_INIT(0);
++static DEFINE_MUTEX(blk_probe_mutex);
++static int blk_probes_ref;
+
+ static void blk_register_tracepoints(void);
+ static void blk_unregister_tracepoints(void);
+@@ -300,11 +301,26 @@ static void blk_trace_free(struct blk_tr
+ kfree(bt);
+ }
+
++static void get_probe_ref(void)
++{
++ mutex_lock(&blk_probe_mutex);
++ if (++blk_probes_ref == 1)
++ blk_register_tracepoints();
++ mutex_unlock(&blk_probe_mutex);
++}
++
++static void put_probe_ref(void)
++{
++ mutex_lock(&blk_probe_mutex);
++ if (!--blk_probes_ref)
++ blk_unregister_tracepoints();
++ mutex_unlock(&blk_probe_mutex);
++}
++
+ static void blk_trace_cleanup(struct blk_trace *bt)
+ {
+ blk_trace_free(bt);
+- if (atomic_dec_and_test(&blk_probes_ref))
+- blk_unregister_tracepoints();
++ put_probe_ref();
+ }
+
+ int blk_trace_remove(struct request_queue *q)
+@@ -522,8 +538,7 @@ int do_blk_trace_setup(struct request_qu
+ if (cmpxchg(&q->blk_trace, NULL, bt))
+ goto err;
+
+- if (atomic_inc_return(&blk_probes_ref) == 1)
+- blk_register_tracepoints();
++ get_probe_ref();
+
+ return 0;
+ err:
+@@ -1466,9 +1481,7 @@ static int blk_trace_remove_queue(struct
+ if (bt == NULL)
+ return -EINVAL;
+
+- if (atomic_dec_and_test(&blk_probes_ref))
+- blk_unregister_tracepoints();
+-
++ put_probe_ref();
+ blk_trace_free(bt);
+ return 0;
+ }
+@@ -1499,8 +1512,7 @@ static int blk_trace_setup_queue(struct
+ if (cmpxchg(&q->blk_trace, NULL, bt))
+ goto free_bt;
+
+- if (atomic_inc_return(&blk_probes_ref) == 1)
+- blk_register_tracepoints();
++ get_probe_ref();
+ return 0;
+
+ free_bt:
--- /dev/null
+From 59b179b48ce2a6076448a44531242ac2b3f6cef2 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Mon, 15 Jan 2018 09:58:27 +0100
+Subject: cfg80211: check dev_set_name() return value
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 59b179b48ce2a6076448a44531242ac2b3f6cef2 upstream.
+
+syzbot reported a warning from rfkill_alloc(), and after a while
+I think that the reason is that it was doing fault injection and
+the dev_set_name() failed, leaving the name NULL, and we didn't
+check the return value and got to rfkill_alloc() with a NULL name.
+Since we really don't want a NULL name, we ought to check the
+return value.
+
+Fixes: fb28ad35906a ("net: struct device - replace bus_id with dev_name(), dev_set_name()")
+Reported-by: syzbot+1ddfb3357e1d7bb5b5d3@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/wireless/core.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -390,6 +390,8 @@ struct wiphy *wiphy_new_nm(const struct
+ if (rv)
+ goto use_default_name;
+ } else {
++ int rv;
++
+ use_default_name:
+ /* NOTE: This is *probably* safe w/out holding rtnl because of
+ * the restrictions on phy names. Probably this call could
+@@ -397,7 +399,11 @@ use_default_name:
+ * phyX. But, might should add some locking and check return
+ * value, and use a different name if this one exists?
+ */
+- dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
++ rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
++ if (rv < 0) {
++ kfree(rdev);
++ return NULL;
++ }
+ }
+
+ INIT_LIST_HEAD(&rdev->wdev_list);
--- /dev/null
+From d8c7fe9f2a486a6e5f0d5229ca43807af5ab22c6 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 18 Dec 2017 16:40:26 -0800
+Subject: crypto: x86/twofish-3way - Fix %rbp usage
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit d8c7fe9f2a486a6e5f0d5229ca43807af5ab22c6 upstream.
+
+Using %rbp as a temporary register breaks frame pointer convention and
+breaks stack traces when unwinding from an interrupt in the crypto code.
+
+In twofish-3way, we can't simply replace %rbp with another register
+because there are none available. Instead, we use the stack to hold the
+values that %rbp, %r11, and %r12 were holding previously. Each of these
+values represents the half of the output from the previous Feistel round
+that is being passed on unchanged to the following round. They are only
+used once per round, when they are exchanged with %rax, %rbx, and %rcx.
+
+As a result, we free up 3 registers (one per block) and can reassign
+them so that %rbp is not used, and additionally %r14 and %r15 are not
+used so they do not need to be saved/restored.
+
+There may be a small overhead caused by replacing 'xchg REG, REG' with
+the needed sequence 'mov MEM, REG; mov REG, MEM; mov REG, REG' once per
+round. But, counterintuitively, when I tested "ctr-twofish-3way" on a
+Haswell processor, the new version was actually about 2% faster.
+(Perhaps 'xchg' is not as well optimized as plain moves.)
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/crypto/twofish-x86_64-asm_64-3way.S | 118 ++++++++++++++-------------
+ 1 file changed, 63 insertions(+), 55 deletions(-)
+
+--- a/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
++++ b/arch/x86/crypto/twofish-x86_64-asm_64-3way.S
+@@ -55,29 +55,31 @@
+ #define RAB1bl %bl
+ #define RAB2bl %cl
+
++#define CD0 0x0(%rsp)
++#define CD1 0x8(%rsp)
++#define CD2 0x10(%rsp)
++
++# used only before/after all rounds
+ #define RCD0 %r8
+ #define RCD1 %r9
+ #define RCD2 %r10
+
+-#define RCD0d %r8d
+-#define RCD1d %r9d
+-#define RCD2d %r10d
+-
+-#define RX0 %rbp
+-#define RX1 %r11
+-#define RX2 %r12
+-
+-#define RX0d %ebp
+-#define RX1d %r11d
+-#define RX2d %r12d
+-
+-#define RY0 %r13
+-#define RY1 %r14
+-#define RY2 %r15
+-
+-#define RY0d %r13d
+-#define RY1d %r14d
+-#define RY2d %r15d
++# used only during rounds
++#define RX0 %r8
++#define RX1 %r9
++#define RX2 %r10
++
++#define RX0d %r8d
++#define RX1d %r9d
++#define RX2d %r10d
++
++#define RY0 %r11
++#define RY1 %r12
++#define RY2 %r13
++
++#define RY0d %r11d
++#define RY1d %r12d
++#define RY2d %r13d
+
+ #define RT0 %rdx
+ #define RT1 %rsi
+@@ -85,6 +87,8 @@
+ #define RT0d %edx
+ #define RT1d %esi
+
++#define RT1bl %sil
++
+ #define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
+ movzbl ab ## bl, tmp2 ## d; \
+ movzbl ab ## bh, tmp1 ## d; \
+@@ -92,6 +96,11 @@
+ op1##l T0(CTX, tmp2, 4), dst ## d; \
+ op2##l T1(CTX, tmp1, 4), dst ## d;
+
++#define swap_ab_with_cd(ab, cd, tmp) \
++ movq cd, tmp; \
++ movq ab, cd; \
++ movq tmp, ab;
++
+ /*
+ * Combined G1 & G2 function. Reordered with help of rotates to have moves
+ * at begining.
+@@ -110,15 +119,15 @@
+ /* G1,2 && G2,2 */ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
+- xchgq cd ## 0, ab ## 0; \
++ swap_ab_with_cd(ab ## 0, cd ## 0, RT0); \
+ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
+- xchgq cd ## 1, ab ## 1; \
++ swap_ab_with_cd(ab ## 1, cd ## 1, RT0); \
+ \
+ do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
+ do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
+- xchgq cd ## 2, ab ## 2;
++ swap_ab_with_cd(ab ## 2, cd ## 2, RT0);
+
+ #define enc_round_end(ab, x, y, n) \
+ addl y ## d, x ## d; \
+@@ -168,6 +177,16 @@
+ decrypt_round3(ba, dc, (n*2)+1); \
+ decrypt_round3(ba, dc, (n*2));
+
++#define push_cd() \
++ pushq RCD2; \
++ pushq RCD1; \
++ pushq RCD0;
++
++#define pop_cd() \
++ popq RCD0; \
++ popq RCD1; \
++ popq RCD2;
++
+ #define inpack3(in, n, xy, m) \
+ movq 4*(n)(in), xy ## 0; \
+ xorq w+4*m(CTX), xy ## 0; \
+@@ -223,11 +242,8 @@ ENTRY(__twofish_enc_blk_3way)
+ * %rdx: src, RIO
+ * %rcx: bool, if true: xor output
+ */
+- pushq %r15;
+- pushq %r14;
+ pushq %r13;
+ pushq %r12;
+- pushq %rbp;
+ pushq %rbx;
+
+ pushq %rcx; /* bool xor */
+@@ -235,40 +251,36 @@ ENTRY(__twofish_enc_blk_3way)
+
+ inpack_enc3();
+
+- encrypt_cycle3(RAB, RCD, 0);
+- encrypt_cycle3(RAB, RCD, 1);
+- encrypt_cycle3(RAB, RCD, 2);
+- encrypt_cycle3(RAB, RCD, 3);
+- encrypt_cycle3(RAB, RCD, 4);
+- encrypt_cycle3(RAB, RCD, 5);
+- encrypt_cycle3(RAB, RCD, 6);
+- encrypt_cycle3(RAB, RCD, 7);
++ push_cd();
++ encrypt_cycle3(RAB, CD, 0);
++ encrypt_cycle3(RAB, CD, 1);
++ encrypt_cycle3(RAB, CD, 2);
++ encrypt_cycle3(RAB, CD, 3);
++ encrypt_cycle3(RAB, CD, 4);
++ encrypt_cycle3(RAB, CD, 5);
++ encrypt_cycle3(RAB, CD, 6);
++ encrypt_cycle3(RAB, CD, 7);
++ pop_cd();
+
+ popq RIO; /* dst */
+- popq %rbp; /* bool xor */
++ popq RT1; /* bool xor */
+
+- testb %bpl, %bpl;
++ testb RT1bl, RT1bl;
+ jnz .L__enc_xor3;
+
+ outunpack_enc3(mov);
+
+ popq %rbx;
+- popq %rbp;
+ popq %r12;
+ popq %r13;
+- popq %r14;
+- popq %r15;
+ ret;
+
+ .L__enc_xor3:
+ outunpack_enc3(xor);
+
+ popq %rbx;
+- popq %rbp;
+ popq %r12;
+ popq %r13;
+- popq %r14;
+- popq %r15;
+ ret;
+ ENDPROC(__twofish_enc_blk_3way)
+
+@@ -278,35 +290,31 @@ ENTRY(twofish_dec_blk_3way)
+ * %rsi: dst
+ * %rdx: src, RIO
+ */
+- pushq %r15;
+- pushq %r14;
+ pushq %r13;
+ pushq %r12;
+- pushq %rbp;
+ pushq %rbx;
+
+ pushq %rsi; /* dst */
+
+ inpack_dec3();
+
+- decrypt_cycle3(RAB, RCD, 7);
+- decrypt_cycle3(RAB, RCD, 6);
+- decrypt_cycle3(RAB, RCD, 5);
+- decrypt_cycle3(RAB, RCD, 4);
+- decrypt_cycle3(RAB, RCD, 3);
+- decrypt_cycle3(RAB, RCD, 2);
+- decrypt_cycle3(RAB, RCD, 1);
+- decrypt_cycle3(RAB, RCD, 0);
++ push_cd();
++ decrypt_cycle3(RAB, CD, 7);
++ decrypt_cycle3(RAB, CD, 6);
++ decrypt_cycle3(RAB, CD, 5);
++ decrypt_cycle3(RAB, CD, 4);
++ decrypt_cycle3(RAB, CD, 3);
++ decrypt_cycle3(RAB, CD, 2);
++ decrypt_cycle3(RAB, CD, 1);
++ decrypt_cycle3(RAB, CD, 0);
++ pop_cd();
+
+ popq RIO; /* dst */
+
+ outunpack_dec3();
+
+ popq %rbx;
+- popq %rbp;
+ popq %r12;
+ popq %r13;
+- popq %r14;
+- popq %r15;
+ ret;
+ ENDPROC(twofish_dec_blk_3way)
--- /dev/null
+From d18d1a5ac811d12f7ebc1129230312b5f2c50cb8 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Tue, 31 Oct 2017 11:55:35 +0000
+Subject: drm: Require __GFP_NOFAIL for the legacy drm_modeset_lock_all
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit d18d1a5ac811d12f7ebc1129230312b5f2c50cb8 upstream.
+
+To acquire all modeset locks requires a ww_ctx to be allocated. As this
+is the legacy path and the allocation small, to reduce the changes
+required (and complex untested error handling) to the legacy drivers, we
+simply assume that the allocation succeeds. At present, it relies on the
+too-small-to-fail rule, but syzbot found that by injecting a failure
+here we would hit the WARN. Document that this allocation must succeed
+with __GFP_NOFAIL.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20171031115535.15166-1-chris@chris-wilson.co.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_modeset_lock.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/drm_modeset_lock.c
++++ b/drivers/gpu/drm/drm_modeset_lock.c
+@@ -69,7 +69,7 @@ void drm_modeset_lock_all(struct drm_dev
+ struct drm_modeset_acquire_ctx *ctx;
+ int ret;
+
+- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | __GFP_NOFAIL);
+ if (WARN_ON(!ctx))
+ return;
+
--- /dev/null
+From efdab992813fb2ed825745625b83c05032e9cda2 Mon Sep 17 00:00:00 2001
+From: Wanpeng Li <wanpeng.li@hotmail.com>
+Date: Wed, 13 Dec 2017 10:46:40 +0100
+Subject: KVM: x86: fix escape of guest dr6 to the host
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wanpeng Li <wanpeng.li@hotmail.com>
+
+commit efdab992813fb2ed825745625b83c05032e9cda2 upstream.
+
+syzkaller reported:
+
+ WARNING: CPU: 0 PID: 12927 at arch/x86/kernel/traps.c:780 do_debug+0x222/0x250
+ CPU: 0 PID: 12927 Comm: syz-executor Tainted: G OE 4.15.0-rc2+ #16
+ RIP: 0010:do_debug+0x222/0x250
+ Call Trace:
+ <#DB>
+ debug+0x3e/0x70
+ RIP: 0010:copy_user_enhanced_fast_string+0x10/0x20
+ </#DB>
+ _copy_from_user+0x5b/0x90
+ SyS_timer_create+0x33/0x80
+ entry_SYSCALL_64_fastpath+0x23/0x9a
+
+The testcase sets a watchpoint (with perf_event_open) on a buffer that is
+passed to timer_create() as the struct sigevent argument. In timer_create(),
+copy_from_user()'s rep movsb triggers the BP. The testcase also sets
+the debug registers for the guest.
+
+However, KVM only restores host debug registers when the host has active
+watchpoints, which triggers a race condition when running the testcase with
+multiple threads. The guest's DR6.BS bit can escape to the host before
+another thread invokes timer_create(), and do_debug() complains.
+
+The fix is to respect do_debug()'s dr6 invariant when leaving KVM.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Radim Krčmář <rkrcmar@redhat.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/x86.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2755,6 +2755,12 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
+ kvm_x86_ops->vcpu_put(vcpu);
+ kvm_put_guest_fpu(vcpu);
+ vcpu->arch.last_host_tsc = rdtsc();
++ /*
++ * If userspace has set any breakpoints or watchpoints, dr6 is restored
++ * on every vmexit, but if not, we might have a stale dr6 from the
++ * guest. do_debug expects dr6 to be cleared after it runs, do the same.
++ */
++ set_debugreg(0, 6);
+ }
+
+ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
--- /dev/null
+From bb422a738f6566f7439cd347d54e321e4fe92a9f Mon Sep 17 00:00:00 2001
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Date: Mon, 18 Dec 2017 20:31:41 +0900
+Subject: mm,vmscan: Make unregister_shrinker() no-op if register_shrinker() failed.
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+commit bb422a738f6566f7439cd347d54e321e4fe92a9f upstream.
+
+Syzbot caught an oops at unregister_shrinker() because combination of
+commit 1d3d4437eae1bb29 ("vmscan: per-node deferred work") and fault
+injection made register_shrinker() fail and the caller of
+register_shrinker() did not check for failure.
+
+----------
+[ 554.881422] FAULT_INJECTION: forcing a failure.
+[ 554.881422] name failslab, interval 1, probability 0, space 0, times 0
+[ 554.881438] CPU: 1 PID: 13231 Comm: syz-executor1 Not tainted 4.14.0-rc8+ #82
+[ 554.881443] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+[ 554.881445] Call Trace:
+[ 554.881459] dump_stack+0x194/0x257
+[ 554.881474] ? arch_local_irq_restore+0x53/0x53
+[ 554.881486] ? find_held_lock+0x35/0x1d0
+[ 554.881507] should_fail+0x8c0/0xa40
+[ 554.881522] ? fault_create_debugfs_attr+0x1f0/0x1f0
+[ 554.881537] ? check_noncircular+0x20/0x20
+[ 554.881546] ? find_next_zero_bit+0x2c/0x40
+[ 554.881560] ? ida_get_new_above+0x421/0x9d0
+[ 554.881577] ? find_held_lock+0x35/0x1d0
+[ 554.881594] ? __lock_is_held+0xb6/0x140
+[ 554.881628] ? check_same_owner+0x320/0x320
+[ 554.881634] ? lock_downgrade+0x990/0x990
+[ 554.881649] ? find_held_lock+0x35/0x1d0
+[ 554.881672] should_failslab+0xec/0x120
+[ 554.881684] __kmalloc+0x63/0x760
+[ 554.881692] ? lock_downgrade+0x990/0x990
+[ 554.881712] ? register_shrinker+0x10e/0x2d0
+[ 554.881721] ? trace_event_raw_event_module_request+0x320/0x320
+[ 554.881737] register_shrinker+0x10e/0x2d0
+[ 554.881747] ? prepare_kswapd_sleep+0x1f0/0x1f0
+[ 554.881755] ? _down_write_nest_lock+0x120/0x120
+[ 554.881765] ? memcpy+0x45/0x50
+[ 554.881785] sget_userns+0xbcd/0xe20
+(...snipped...)
+[ 554.898693] kasan: CONFIG_KASAN_INLINE enabled
+[ 554.898724] kasan: GPF could be caused by NULL-ptr deref or user memory access
+[ 554.898732] general protection fault: 0000 [#1] SMP KASAN
+[ 554.898737] Dumping ftrace buffer:
+[ 554.898741] (ftrace buffer empty)
+[ 554.898743] Modules linked in:
+[ 554.898752] CPU: 1 PID: 13231 Comm: syz-executor1 Not tainted 4.14.0-rc8+ #82
+[ 554.898755] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+[ 554.898760] task: ffff8801d1dbe5c0 task.stack: ffff8801c9e38000
+[ 554.898772] RIP: 0010:__list_del_entry_valid+0x7e/0x150
+[ 554.898775] RSP: 0018:ffff8801c9e3f108 EFLAGS: 00010246
+[ 554.898780] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+[ 554.898784] RDX: 0000000000000000 RSI: ffff8801c53c6f98 RDI: ffff8801c53c6fa0
+[ 554.898788] RBP: ffff8801c9e3f120 R08: 1ffff100393c7d55 R09: 0000000000000004
+[ 554.898791] R10: ffff8801c9e3ef70 R11: 0000000000000000 R12: 0000000000000000
+[ 554.898795] R13: dffffc0000000000 R14: 1ffff100393c7e45 R15: ffff8801c53c6f98
+[ 554.898800] FS: 0000000000000000(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000
+[ 554.898804] CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033
+[ 554.898807] CR2: 00000000dbc23000 CR3: 00000001c7269000 CR4: 00000000001406e0
+[ 554.898813] DR0: 0000000020000000 DR1: 0000000020000000 DR2: 0000000000000000
+[ 554.898816] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000600
+[ 554.898818] Call Trace:
+[ 554.898828] unregister_shrinker+0x79/0x300
+[ 554.898837] ? perf_trace_mm_vmscan_writepage+0x750/0x750
+[ 554.898844] ? down_write+0x87/0x120
+[ 554.898851] ? deactivate_super+0x139/0x1b0
+[ 554.898857] ? down_read+0x150/0x150
+[ 554.898864] ? check_same_owner+0x320/0x320
+[ 554.898875] deactivate_locked_super+0x64/0xd0
+[ 554.898883] deactivate_super+0x141/0x1b0
+----------
+
+Since allowing register_shrinker() callers to call unregister_shrinker()
+when register_shrinker() failed can simplify error recovery path, this
+patch makes unregister_shrinker() no-op when register_shrinker() failed.
+Also, reset shrinker->nr_deferred in case unregister_shrinker() was
+by error called twice.
+
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Aliaksei Karaliou <akaraliou.dev@gmail.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Cc: Glauber Costa <glauber@scylladb.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/vmscan.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -254,10 +254,13 @@ EXPORT_SYMBOL(register_shrinker);
+ */
+ void unregister_shrinker(struct shrinker *shrinker)
+ {
++ if (!shrinker->nr_deferred)
++ return;
+ down_write(&shrinker_rwsem);
+ list_del(&shrinker->list);
+ up_write(&shrinker_rwsem);
+ kfree(shrinker->nr_deferred);
++ shrinker->nr_deferred = NULL;
+ }
+ EXPORT_SYMBOL(unregister_shrinker);
+
--- /dev/null
+From 911362c70df5b766c243dc297fadeaced786ffd8 Mon Sep 17 00:00:00 2001
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Fri, 12 Feb 2016 15:43:53 +0100
+Subject: net: add dst_cache support
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+commit 911362c70df5b766c243dc297fadeaced786ffd8 upstream.
+
+This patch add a generic, lockless dst cache implementation.
+The need for lock is avoided updating the dst cache fields
+only in per cpu scope, and requiring that the cache manipulation
+functions are invoked with the local bh disabled.
+
+The refresh_ts and reset_ts fields are used to ensure the cache
+consistency in case of cuncurrent cache update (dst_cache_set*) and
+reset operation (dst_cache_reset).
+
+Consider the following scenario:
+
+CPU1: CPU2:
+ <cache lookup with emtpy cache: it fails>
+ <get dst via uncached route lookup>
+ <related configuration changes>
+ dst_cache_reset()
+ dst_cache_set()
+
+The dst entry set passed to dst_cache_set() should not be used
+for later dst cache lookup, because it's obtained using old
+configuration values.
+
+Since the refresh_ts is updated only on dst_cache lookup, the
+cached value in the above scenario will be discarded on the next
+lookup.
+
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Suggested-and-acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Manoj Boopathi Raj <manojboopathi@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/dst_cache.h | 97 +++++++++++++++++++++++++++
+ net/Kconfig | 4 +
+ net/core/Makefile | 1
+ net/core/dst_cache.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 270 insertions(+)
+
+--- /dev/null
++++ b/include/net/dst_cache.h
+@@ -0,0 +1,97 @@
++#ifndef _NET_DST_CACHE_H
++#define _NET_DST_CACHE_H
++
++#include <linux/jiffies.h>
++#include <net/dst.h>
++#if IS_ENABLED(CONFIG_IPV6)
++#include <net/ip6_fib.h>
++#endif
++
++struct dst_cache {
++ struct dst_cache_pcpu __percpu *cache;
++ unsigned long reset_ts;
++};
++
++/**
++ * dst_cache_get - perform cache lookup
++ * @dst_cache: the cache
++ *
++ * The caller should use dst_cache_get_ip4() if it need to retrieve the
++ * source address to be used when xmitting to the cached dst.
++ * local BH must be disabled.
++ */
++struct dst_entry *dst_cache_get(struct dst_cache *dst_cache);
++
++/**
++ * dst_cache_get_ip4 - perform cache lookup and fetch ipv4 source address
++ * @dst_cache: the cache
++ * @saddr: return value for the retrieved source address
++ *
++ * local BH must be disabled.
++ */
++struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr);
++
++/**
++ * dst_cache_set_ip4 - store the ipv4 dst into the cache
++ * @dst_cache: the cache
++ * @dst: the entry to be cached
++ * @saddr: the source address to be stored inside the cache
++ *
++ * local BH must be disabled.
++ */
++void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst,
++ __be32 saddr);
++
++#if IS_ENABLED(CONFIG_IPV6)
++
++/**
++ * dst_cache_set_ip6 - store the ipv6 dst into the cache
++ * @dst_cache: the cache
++ * @dst: the entry to be cached
++ * @saddr: the source address to be stored inside the cache
++ *
++ * local BH must be disabled.
++ */
++void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
++ const struct in6_addr *addr);
++
++/**
++ * dst_cache_get_ip6 - perform cache lookup and fetch ipv6 source address
++ * @dst_cache: the cache
++ * @saddr: return value for the retrieved source address
++ *
++ * local BH must be disabled.
++ */
++struct dst_entry *dst_cache_get_ip6(struct dst_cache *dst_cache,
++ struct in6_addr *saddr);
++#endif
++
++/**
++ * dst_cache_reset - invalidate the cache contents
++ * @dst_cache: the cache
++ *
++ * This do not free the cached dst to avoid races and contentions.
++ * the dst will be freed on later cache lookup.
++ */
++static inline void dst_cache_reset(struct dst_cache *dst_cache)
++{
++ dst_cache->reset_ts = jiffies;
++}
++
++/**
++ * dst_cache_init - initialize the cache, allocating the required storage
++ * @dst_cache: the cache
++ * @gfp: allocation flags
++ */
++int dst_cache_init(struct dst_cache *dst_cache, gfp_t gfp);
++
++/**
++ * dst_cache_destroy - empty the cache and free the allocated storage
++ * @dst_cache: the cache
++ *
++ * No synchronization is enforced: it must be called only when the cache
++ * is unsed.
++ */
++void dst_cache_destroy(struct dst_cache *dst_cache);
++
++#endif
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -383,6 +383,10 @@ config LWTUNNEL
+ weight tunnel endpoint. Tunnel encapsulation parameters are stored
+ with light weight tunnel state associated with fib routes.
+
++config DST_CACHE
++ bool "dst cache"
++ default n
++
+ endif # if NET
+
+ # Used by archs to tell that they support BPF_JIT
+--- a/net/core/Makefile
++++ b/net/core/Makefile
+@@ -24,3 +24,4 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_cl
+ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
+ obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
+ obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
++obj-$(CONFIG_DST_CACHE) += dst_cache.o
+--- /dev/null
++++ b/net/core/dst_cache.c
+@@ -0,0 +1,168 @@
++/*
++ * net/core/dst_cache.c - dst entry cache
++ *
++ * Copyright (c) 2016 Paolo Abeni <pabeni@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/percpu.h>
++#include <net/dst_cache.h>
++#include <net/route.h>
++#if IS_ENABLED(CONFIG_IPV6)
++#include <net/ip6_fib.h>
++#endif
++#include <uapi/linux/in.h>
++
++struct dst_cache_pcpu {
++ unsigned long refresh_ts;
++ struct dst_entry *dst;
++ u32 cookie;
++ union {
++ struct in_addr in_saddr;
++ struct in6_addr in6_saddr;
++ };
++};
++
++void dst_cache_per_cpu_dst_set(struct dst_cache_pcpu *dst_cache,
++ struct dst_entry *dst, u32 cookie)
++{
++ dst_release(dst_cache->dst);
++ if (dst)
++ dst_hold(dst);
++
++ dst_cache->cookie = cookie;
++ dst_cache->dst = dst;
++}
++
++struct dst_entry *dst_cache_per_cpu_get(struct dst_cache *dst_cache,
++ struct dst_cache_pcpu *idst)
++{
++ struct dst_entry *dst;
++
++ dst = idst->dst;
++ if (!dst)
++ goto fail;
++
++ /* the cache already hold a dst reference; it can't go away */
++ dst_hold(dst);
++
++ if (unlikely(!time_after(idst->refresh_ts, dst_cache->reset_ts) ||
++ (dst->obsolete && !dst->ops->check(dst, idst->cookie)))) {
++ dst_cache_per_cpu_dst_set(idst, NULL, 0);
++ dst_release(dst);
++ goto fail;
++ }
++ return dst;
++
++fail:
++ idst->refresh_ts = jiffies;
++ return NULL;
++}
++
++struct dst_entry *dst_cache_get(struct dst_cache *dst_cache)
++{
++ if (!dst_cache->cache)
++ return NULL;
++
++ return dst_cache_per_cpu_get(dst_cache, this_cpu_ptr(dst_cache->cache));
++}
++EXPORT_SYMBOL_GPL(dst_cache_get);
++
++struct rtable *dst_cache_get_ip4(struct dst_cache *dst_cache, __be32 *saddr)
++{
++ struct dst_cache_pcpu *idst;
++ struct dst_entry *dst;
++
++ if (!dst_cache->cache)
++ return NULL;
++
++ idst = this_cpu_ptr(dst_cache->cache);
++ dst = dst_cache_per_cpu_get(dst_cache, idst);
++ if (!dst)
++ return NULL;
++
++ *saddr = idst->in_saddr.s_addr;
++ return container_of(dst, struct rtable, dst);
++}
++EXPORT_SYMBOL_GPL(dst_cache_get_ip4);
++
++void dst_cache_set_ip4(struct dst_cache *dst_cache, struct dst_entry *dst,
++ __be32 saddr)
++{
++ struct dst_cache_pcpu *idst;
++
++ if (!dst_cache->cache)
++ return;
++
++ idst = this_cpu_ptr(dst_cache->cache);
++ dst_cache_per_cpu_dst_set(idst, dst, 0);
++ idst->in_saddr.s_addr = saddr;
++}
++EXPORT_SYMBOL_GPL(dst_cache_set_ip4);
++
++#if IS_ENABLED(CONFIG_IPV6)
++void dst_cache_set_ip6(struct dst_cache *dst_cache, struct dst_entry *dst,
++ const struct in6_addr *addr)
++{
++ struct dst_cache_pcpu *idst;
++
++ if (!dst_cache->cache)
++ return;
++
++ idst = this_cpu_ptr(dst_cache->cache);
++ dst_cache_per_cpu_dst_set(this_cpu_ptr(dst_cache->cache), dst,
++ rt6_get_cookie((struct rt6_info *)dst));
++ idst->in6_saddr = *addr;
++}
++EXPORT_SYMBOL_GPL(dst_cache_set_ip6);
++
++struct dst_entry *dst_cache_get_ip6(struct dst_cache *dst_cache,
++ struct in6_addr *saddr)
++{
++ struct dst_cache_pcpu *idst;
++ struct dst_entry *dst;
++
++ if (!dst_cache->cache)
++ return NULL;
++
++ idst = this_cpu_ptr(dst_cache->cache);
++ dst = dst_cache_per_cpu_get(dst_cache, idst);
++ if (!dst)
++ return NULL;
++
++ *saddr = idst->in6_saddr;
++ return dst;
++}
++EXPORT_SYMBOL_GPL(dst_cache_get_ip6);
++#endif
++
++int dst_cache_init(struct dst_cache *dst_cache, gfp_t gfp)
++{
++ dst_cache->cache = alloc_percpu_gfp(struct dst_cache_pcpu,
++ gfp | __GFP_ZERO);
++ if (!dst_cache->cache)
++ return -ENOMEM;
++
++ dst_cache_reset(dst_cache);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(dst_cache_init);
++
++void dst_cache_destroy(struct dst_cache *dst_cache)
++{
++ int i;
++
++ if (!dst_cache->cache)
++ return;
++
++ for_each_possible_cpu(i)
++ dst_release(per_cpu_ptr(dst_cache->cache, i)->dst);
++
++ free_percpu(dst_cache->cache);
++}
++EXPORT_SYMBOL_GPL(dst_cache_destroy);
--- /dev/null
+From 8d74e9f88d65af8bb2e095aff506aa6eac755ada Mon Sep 17 00:00:00 2001
+From: Willem de Bruijn <willemb@google.com>
+Date: Tue, 12 Dec 2017 11:39:04 -0500
+Subject: net: avoid skb_warn_bad_offload on IS_ERR
+
+From: Willem de Bruijn <willemb@google.com>
+
+commit 8d74e9f88d65af8bb2e095aff506aa6eac755ada upstream.
+
+skb_warn_bad_offload warns when packets enter the GSO stack that
+require skb_checksum_help or vice versa. Do not warn on arbitrary
+bad packets. Packet sockets can craft many. Syzkaller was able to
+demonstrate another one with eth_type games.
+
+In particular, suppress the warning when segmentation returns an
+error, which is for reasons other than checksum offload.
+
+See also commit 36c92474498a ("net: WARN if skb_checksum_help() is
+called on skb requiring segmentation") for context on this warning.
+
+Signed-off-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/core/dev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2598,7 +2598,7 @@ struct sk_buff *__skb_gso_segment(struct
+
+ segs = skb_mac_gso_segment(skb, features);
+
+- if (unlikely(skb_needs_check(skb, tx_path)))
++ if (unlikely(skb_needs_check(skb, tx_path) && !IS_ERR(segs)))
+ skb_warn_bad_offload(skb);
+
+ return segs;
--- /dev/null
+From 607f725f6f7d5ec3759fbc16224afb60e2152a5b Mon Sep 17 00:00:00 2001
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Fri, 12 Feb 2016 15:43:54 +0100
+Subject: net: replace dst_cache ip6_tunnel implementation with the generic one
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+commit 607f725f6f7d5ec3759fbc16224afb60e2152a5b upstream.
+
+This also fix a potential race into the existing tunnel code, which
+could lead to the wrong dst to be permanenty cached:
+
+CPU1: CPU2:
+ <xmit on ip6_tunnel>
+ <cache lookup fails>
+ dst = ip6_route_output(...)
+ <tunnel params are changed via nl>
+ dst_cache_reset() // no effect,
+ // the cache is empty
+ dst_cache_set() // the wrong dst
+ // is permanenty stored
+ // into the cache
+
+With the new dst implementation the above race is not possible
+since the first cache lookup after dst_cache_reset will fail due
+to the timestamp check
+
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Suggested-and-acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Manoj Boopathi Raj <manojboopathi@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/ip6_tunnel.h | 15 ----
+ net/ipv6/Kconfig | 1
+ net/ipv6/ip6_gre.c | 12 +--
+ net/ipv6/ip6_tunnel.c | 151 +++++++----------------------------------------
+ net/ipv6/ip6_vti.c | 2
+ 5 files changed, 35 insertions(+), 146 deletions(-)
+
+--- a/include/net/ip6_tunnel.h
++++ b/include/net/ip6_tunnel.h
+@@ -5,6 +5,8 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_tunnel.h>
+ #include <linux/ip6_tunnel.h>
++#include <net/ip_tunnels.h>
++#include <net/dst_cache.h>
+
+ #define IP6TUNNEL_ERR_TIMEO (30*HZ)
+
+@@ -32,12 +34,6 @@ struct __ip6_tnl_parm {
+ __be32 o_key;
+ };
+
+-struct ip6_tnl_dst {
+- seqlock_t lock;
+- struct dst_entry __rcu *dst;
+- u32 cookie;
+-};
+-
+ /* IPv6 tunnel */
+ struct ip6_tnl {
+ struct ip6_tnl __rcu *next; /* next tunnel in list */
+@@ -45,7 +41,7 @@ struct ip6_tnl {
+ struct net *net; /* netns for packet i/o */
+ struct __ip6_tnl_parm parms; /* tunnel configuration parameters */
+ struct flowi fl; /* flowi template for xmit */
+- struct ip6_tnl_dst __percpu *dst_cache; /* cached dst */
++ struct dst_cache dst_cache; /* cached dst */
+
+ int err_count;
+ unsigned long err_time;
+@@ -65,11 +61,6 @@ struct ipv6_tlv_tnl_enc_lim {
+ __u8 encap_limit; /* tunnel encapsulation limit */
+ } __packed;
+
+-struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t);
+-int ip6_tnl_dst_init(struct ip6_tnl *t);
+-void ip6_tnl_dst_destroy(struct ip6_tnl *t);
+-void ip6_tnl_dst_reset(struct ip6_tnl *t);
+-void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst);
+ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
+ const struct in6_addr *raddr);
+ int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
+--- a/net/ipv6/Kconfig
++++ b/net/ipv6/Kconfig
+@@ -205,6 +205,7 @@ config IPV6_NDISC_NODETYPE
+ config IPV6_TUNNEL
+ tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)"
+ select INET6_TUNNEL
++ select DST_CACHE
+ ---help---
+ Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in
+ RFC 2473.
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -362,7 +362,7 @@ static void ip6gre_tunnel_uninit(struct
+ struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
+
+ ip6gre_tunnel_unlink(ign, t);
+- ip6_tnl_dst_reset(t);
++ dst_cache_reset(&t->dst_cache);
+ dev_put(dev);
+ }
+
+@@ -640,7 +640,7 @@ static netdev_tx_t ip6gre_xmit2(struct s
+ }
+
+ if (!fl6->flowi6_mark)
+- dst = ip6_tnl_dst_get(tunnel);
++ dst = dst_cache_get(&tunnel->dst_cache);
+
+ if (!dst) {
+ dst = ip6_route_output(net, NULL, fl6);
+@@ -709,7 +709,7 @@ static netdev_tx_t ip6gre_xmit2(struct s
+ }
+
+ if (!fl6->flowi6_mark && ndst)
+- ip6_tnl_dst_set(tunnel, ndst);
++ dst_cache_set_ip6(&tunnel->dst_cache, ndst, &fl6->saddr);
+ skb_dst_set(skb, dst);
+
+ proto = NEXTHDR_GRE;
+@@ -1017,7 +1017,7 @@ static int ip6gre_tnl_change(struct ip6_
+ t->parms.o_key = p->o_key;
+ t->parms.i_flags = p->i_flags;
+ t->parms.o_flags = p->o_flags;
+- ip6_tnl_dst_reset(t);
++ dst_cache_reset(&t->dst_cache);
+ ip6gre_tnl_link_config(t, set_mtu);
+ return 0;
+ }
+@@ -1228,7 +1228,7 @@ static void ip6gre_dev_free(struct net_d
+ {
+ struct ip6_tnl *t = netdev_priv(dev);
+
+- ip6_tnl_dst_destroy(t);
++ dst_cache_destroy(&t->dst_cache);
+ free_percpu(dev->tstats);
+ free_netdev(dev);
+ }
+@@ -1266,7 +1266,7 @@ static int ip6gre_tunnel_init_common(str
+ if (!dev->tstats)
+ return -ENOMEM;
+
+- ret = ip6_tnl_dst_init(tunnel);
++ ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+ if (ret) {
+ free_percpu(dev->tstats);
+ dev->tstats = NULL;
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -122,97 +122,6 @@ static struct net_device_stats *ip6_get_
+ return &dev->stats;
+ }
+
+-/*
+- * Locking : hash tables are protected by RCU and RTNL
+- */
+-
+-static void ip6_tnl_per_cpu_dst_set(struct ip6_tnl_dst *idst,
+- struct dst_entry *dst)
+-{
+- write_seqlock_bh(&idst->lock);
+- dst_release(rcu_dereference_protected(
+- idst->dst,
+- lockdep_is_held(&idst->lock.lock)));
+- if (dst) {
+- dst_hold(dst);
+- idst->cookie = rt6_get_cookie((struct rt6_info *)dst);
+- } else {
+- idst->cookie = 0;
+- }
+- rcu_assign_pointer(idst->dst, dst);
+- write_sequnlock_bh(&idst->lock);
+-}
+-
+-struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t)
+-{
+- struct ip6_tnl_dst *idst;
+- struct dst_entry *dst;
+- unsigned int seq;
+- u32 cookie;
+-
+- idst = raw_cpu_ptr(t->dst_cache);
+-
+- rcu_read_lock();
+- do {
+- seq = read_seqbegin(&idst->lock);
+- dst = rcu_dereference(idst->dst);
+- cookie = idst->cookie;
+- } while (read_seqretry(&idst->lock, seq));
+-
+- if (dst && !atomic_inc_not_zero(&dst->__refcnt))
+- dst = NULL;
+- rcu_read_unlock();
+-
+- if (dst && dst->obsolete && !dst->ops->check(dst, cookie)) {
+- ip6_tnl_per_cpu_dst_set(idst, NULL);
+- dst_release(dst);
+- dst = NULL;
+- }
+- return dst;
+-}
+-EXPORT_SYMBOL_GPL(ip6_tnl_dst_get);
+-
+-void ip6_tnl_dst_reset(struct ip6_tnl *t)
+-{
+- int i;
+-
+- for_each_possible_cpu(i)
+- ip6_tnl_per_cpu_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
+-}
+-EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset);
+-
+-void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst)
+-{
+- ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), dst);
+-
+-}
+-EXPORT_SYMBOL_GPL(ip6_tnl_dst_set);
+-
+-void ip6_tnl_dst_destroy(struct ip6_tnl *t)
+-{
+- if (!t->dst_cache)
+- return;
+-
+- ip6_tnl_dst_reset(t);
+- free_percpu(t->dst_cache);
+-}
+-EXPORT_SYMBOL_GPL(ip6_tnl_dst_destroy);
+-
+-int ip6_tnl_dst_init(struct ip6_tnl *t)
+-{
+- int i;
+-
+- t->dst_cache = alloc_percpu(struct ip6_tnl_dst);
+- if (!t->dst_cache)
+- return -ENOMEM;
+-
+- for_each_possible_cpu(i)
+- seqlock_init(&per_cpu_ptr(t->dst_cache, i)->lock);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(ip6_tnl_dst_init);
+-
+ /**
+ * ip6_tnl_lookup - fetch tunnel matching the end-point addresses
+ * @remote: the address of the tunnel exit-point
+@@ -331,7 +240,7 @@ static void ip6_dev_free(struct net_devi
+ {
+ struct ip6_tnl *t = netdev_priv(dev);
+
+- ip6_tnl_dst_destroy(t);
++ dst_cache_destroy(&t->dst_cache);
+ free_percpu(dev->tstats);
+ free_netdev(dev);
+ }
+@@ -464,7 +373,7 @@ ip6_tnl_dev_uninit(struct net_device *de
+ RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL);
+ else
+ ip6_tnl_unlink(ip6n, t);
+- ip6_tnl_dst_reset(t);
++ dst_cache_reset(&t->dst_cache);
+ dev_put(dev);
+ }
+
+@@ -1053,7 +962,6 @@ static int ip6_tnl_xmit2(struct sk_buff
+ struct ipv6_tel_txoption opt;
+ struct dst_entry *dst = NULL, *ndst = NULL;
+ struct net_device *tdev;
+- bool use_cache = false;
+ int mtu;
+ unsigned int max_headroom = sizeof(struct ipv6hdr);
+ u8 proto;
+@@ -1061,39 +969,28 @@ static int ip6_tnl_xmit2(struct sk_buff
+
+ /* NBMA tunnel */
+ if (ipv6_addr_any(&t->parms.raddr)) {
+- if (skb->protocol == htons(ETH_P_IPV6)) {
+- struct in6_addr *addr6;
+- struct neighbour *neigh;
+- int addr_type;
+-
+- if (!skb_dst(skb))
+- goto tx_err_link_failure;
+-
+- neigh = dst_neigh_lookup(skb_dst(skb),
+- &ipv6_hdr(skb)->daddr);
+- if (!neigh)
+- goto tx_err_link_failure;
++ struct in6_addr *addr6;
++ struct neighbour *neigh;
++ int addr_type;
++
++ if (!skb_dst(skb))
++ goto tx_err_link_failure;
+
+- addr6 = (struct in6_addr *)&neigh->primary_key;
+- addr_type = ipv6_addr_type(addr6);
++ neigh = dst_neigh_lookup(skb_dst(skb),
++ &ipv6_hdr(skb)->daddr);
++ if (!neigh)
++ goto tx_err_link_failure;
+
+- if (addr_type == IPV6_ADDR_ANY)
+- addr6 = &ipv6_hdr(skb)->daddr;
++ addr6 = (struct in6_addr *)&neigh->primary_key;
++ addr_type = ipv6_addr_type(addr6);
+
+- memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+- neigh_release(neigh);
+- }
+- } else if (t->parms.proto != 0 && !(t->parms.flags &
+- (IP6_TNL_F_USE_ORIG_TCLASS |
+- IP6_TNL_F_USE_ORIG_FWMARK))) {
+- /* enable the cache only if neither the outer protocol nor the
+- * routing decision depends on the current inner header value
+- */
+- use_cache = true;
+- }
++ if (addr_type == IPV6_ADDR_ANY)
++ addr6 = &ipv6_hdr(skb)->daddr;
+
+- if (use_cache)
+- dst = ip6_tnl_dst_get(t);
++ memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
++ neigh_release(neigh);
++ } else if (!fl6->flowi6_mark)
++ dst = dst_cache_get(&t->dst_cache);
+
+ if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
+ goto tx_err_link_failure;
+@@ -1156,8 +1053,8 @@ static int ip6_tnl_xmit2(struct sk_buff
+ skb = new_skb;
+ }
+
+- if (use_cache && ndst)
+- ip6_tnl_dst_set(t, ndst);
++ if (!fl6->flowi6_mark && ndst)
++ dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr);
+ skb_dst_set(skb, dst);
+
+ skb->transport_header = skb->network_header;
+@@ -1392,7 +1289,7 @@ ip6_tnl_change(struct ip6_tnl *t, const
+ t->parms.flowinfo = p->flowinfo;
+ t->parms.link = p->link;
+ t->parms.proto = p->proto;
+- ip6_tnl_dst_reset(t);
++ dst_cache_reset(&t->dst_cache);
+ ip6_tnl_link_config(t);
+ return 0;
+ }
+@@ -1663,7 +1560,7 @@ ip6_tnl_dev_init_gen(struct net_device *
+ if (!dev->tstats)
+ return -ENOMEM;
+
+- ret = ip6_tnl_dst_init(t);
++ ret = dst_cache_init(&t->dst_cache, GFP_KERNEL);
+ if (ret) {
+ free_percpu(dev->tstats);
+ dev->tstats = NULL;
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -645,7 +645,7 @@ vti6_tnl_change(struct ip6_tnl *t, const
+ t->parms.i_key = p->i_key;
+ t->parms.o_key = p->o_key;
+ t->parms.proto = p->proto;
+- ip6_tnl_dst_reset(t);
++ dst_cache_reset(&t->dst_cache);
+ vti6_link_config(t);
+ return 0;
+ }
--- /dev/null
+From 1a38956cce5eabd7b74f94bab70265e4df83165e Mon Sep 17 00:00:00 2001
+From: Dmitry Vyukov <dvyukov@google.com>
+Date: Tue, 30 Jan 2018 15:21:34 +0100
+Subject: netfilter: ipt_CLUSTERIP: fix out-of-bounds accesses in clusterip_tg_check()
+
+From: Dmitry Vyukov <dvyukov@google.com>
+
+commit 1a38956cce5eabd7b74f94bab70265e4df83165e upstream.
+
+Commit 136e92bbec0a switched local_nodes from an array to a bitmask
+but did not add proper bounds checks. As the result
+clusterip_config_init_nodelist() can both over-read
+ipt_clusterip_tgt_info.local_nodes and over-write
+clusterip_config.local_nodes.
+
+Add bounds checks for both.
+
+Fixes: 136e92bbec0a ("[NETFILTER] CLUSTERIP: use a bitmap to store node responsibility data")
+Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv4/netfilter/ipt_CLUSTERIP.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+@@ -365,7 +365,7 @@ static int clusterip_tg_check(const stru
+ struct ipt_clusterip_tgt_info *cipinfo = par->targinfo;
+ const struct ipt_entry *e = par->entryinfo;
+ struct clusterip_config *config;
+- int ret;
++ int ret, i;
+
+ if (par->nft_compat) {
+ pr_err("cannot use CLUSTERIP target from nftables compat\n");
+@@ -384,8 +384,18 @@ static int clusterip_tg_check(const stru
+ pr_info("Please specify destination IP\n");
+ return -EINVAL;
+ }
+-
+- /* FIXME: further sanity checks */
++ if (cipinfo->num_local_nodes > ARRAY_SIZE(cipinfo->local_nodes)) {
++ pr_info("bad num_local_nodes %u\n", cipinfo->num_local_nodes);
++ return -EINVAL;
++ }
++ for (i = 0; i < cipinfo->num_local_nodes; i++) {
++ if (cipinfo->local_nodes[i] - 1 >=
++ sizeof(config->local_nodes) * 8) {
++ pr_info("bad local_nodes[%d] %u\n",
++ i, cipinfo->local_nodes[i]);
++ return -EINVAL;
++ }
++ }
+
+ config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1);
+ if (!config) {
--- /dev/null
+From 3f34cfae1238848fd53f25e5c8fd59da57901f4b Mon Sep 17 00:00:00 2001
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Tue, 30 Jan 2018 19:01:40 +0100
+Subject: netfilter: on sockopt() acquire sock lock only in the required scope
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+commit 3f34cfae1238848fd53f25e5c8fd59da57901f4b upstream.
+
+Syzbot reported several deadlocks in the netfilter area caused by
+rtnl lock and socket lock being acquired with a different order on
+different code paths, leading to backtraces like the following one:
+
+======================================================
+WARNING: possible circular locking dependency detected
+4.15.0-rc9+ #212 Not tainted
+------------------------------------------------------
+syzkaller041579/3682 is trying to acquire lock:
+ (sk_lock-AF_INET6){+.+.}, at: [<000000008775e4dd>] lock_sock
+include/net/sock.h:1463 [inline]
+ (sk_lock-AF_INET6){+.+.}, at: [<000000008775e4dd>]
+do_ipv6_setsockopt.isra.8+0x3c5/0x39d0 net/ipv6/ipv6_sockglue.c:167
+
+but task is already holding lock:
+ (rtnl_mutex){+.+.}, at: [<000000004342eaa9>] rtnl_lock+0x17/0x20
+net/core/rtnetlink.c:74
+
+which lock already depends on the new lock.
+
+the existing dependency chain (in reverse order) is:
+
+-> #1 (rtnl_mutex){+.+.}:
+ __mutex_lock_common kernel/locking/mutex.c:756 [inline]
+ __mutex_lock+0x16f/0x1a80 kernel/locking/mutex.c:893
+ mutex_lock_nested+0x16/0x20 kernel/locking/mutex.c:908
+ rtnl_lock+0x17/0x20 net/core/rtnetlink.c:74
+ register_netdevice_notifier+0xad/0x860 net/core/dev.c:1607
+ tee_tg_check+0x1a0/0x280 net/netfilter/xt_TEE.c:106
+ xt_check_target+0x22c/0x7d0 net/netfilter/x_tables.c:845
+ check_target net/ipv6/netfilter/ip6_tables.c:538 [inline]
+ find_check_entry.isra.7+0x935/0xcf0
+net/ipv6/netfilter/ip6_tables.c:580
+ translate_table+0xf52/0x1690 net/ipv6/netfilter/ip6_tables.c:749
+ do_replace net/ipv6/netfilter/ip6_tables.c:1165 [inline]
+ do_ip6t_set_ctl+0x370/0x5f0 net/ipv6/netfilter/ip6_tables.c:1691
+ nf_sockopt net/netfilter/nf_sockopt.c:106 [inline]
+ nf_setsockopt+0x67/0xc0 net/netfilter/nf_sockopt.c:115
+ ipv6_setsockopt+0x115/0x150 net/ipv6/ipv6_sockglue.c:928
+ udpv6_setsockopt+0x45/0x80 net/ipv6/udp.c:1422
+ sock_common_setsockopt+0x95/0xd0 net/core/sock.c:2978
+ SYSC_setsockopt net/socket.c:1849 [inline]
+ SyS_setsockopt+0x189/0x360 net/socket.c:1828
+ entry_SYSCALL_64_fastpath+0x29/0xa0
+
+-> #0 (sk_lock-AF_INET6){+.+.}:
+ lock_acquire+0x1d5/0x580 kernel/locking/lockdep.c:3914
+ lock_sock_nested+0xc2/0x110 net/core/sock.c:2780
+ lock_sock include/net/sock.h:1463 [inline]
+ do_ipv6_setsockopt.isra.8+0x3c5/0x39d0 net/ipv6/ipv6_sockglue.c:167
+ ipv6_setsockopt+0xd7/0x150 net/ipv6/ipv6_sockglue.c:922
+ udpv6_setsockopt+0x45/0x80 net/ipv6/udp.c:1422
+ sock_common_setsockopt+0x95/0xd0 net/core/sock.c:2978
+ SYSC_setsockopt net/socket.c:1849 [inline]
+ SyS_setsockopt+0x189/0x360 net/socket.c:1828
+ entry_SYSCALL_64_fastpath+0x29/0xa0
+
+other info that might help us debug this:
+
+ Possible unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock(rtnl_mutex);
+ lock(sk_lock-AF_INET6);
+ lock(rtnl_mutex);
+ lock(sk_lock-AF_INET6);
+
+ *** DEADLOCK ***
+
+1 lock held by syzkaller041579/3682:
+ #0: (rtnl_mutex){+.+.}, at: [<000000004342eaa9>] rtnl_lock+0x17/0x20
+net/core/rtnetlink.c:74
+
+The problem, as Florian noted, is that nf_setsockopt() is always
+called with the socket held, even if the lock itself is required only
+for very tight scopes and only for some operation.
+
+This patch addresses the issues moving the lock_sock() call only
+where really needed, namely in ipv*_getorigdst(), so that nf_setsockopt()
+does not need anymore to acquire both locks.
+
+Fixes: 22265a5c3c10 ("netfilter: xt_TEE: resolve oif using netdevice notifiers")
+Reported-by: syzbot+a4c2dc980ac1af699b36@syzkaller.appspotmail.com
+Suggested-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv4/ip_sockglue.c | 14 ++++----------
+ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 +++++-
+ net/ipv6/ipv6_sockglue.c | 17 +++++------------
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 18 ++++++++++++------
+ 4 files changed, 26 insertions(+), 29 deletions(-)
+
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -1221,11 +1221,8 @@ int ip_setsockopt(struct sock *sk, int l
+ if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
+ optname != IP_IPSEC_POLICY &&
+ optname != IP_XFRM_POLICY &&
+- !ip_mroute_opt(optname)) {
+- lock_sock(sk);
++ !ip_mroute_opt(optname))
+ err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
+- release_sock(sk);
+- }
+ #endif
+ return err;
+ }
+@@ -1250,12 +1247,9 @@ int compat_ip_setsockopt(struct sock *sk
+ if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
+ optname != IP_IPSEC_POLICY &&
+ optname != IP_XFRM_POLICY &&
+- !ip_mroute_opt(optname)) {
+- lock_sock(sk);
+- err = compat_nf_setsockopt(sk, PF_INET, optname,
+- optval, optlen);
+- release_sock(sk);
+- }
++ !ip_mroute_opt(optname))
++ err = compat_nf_setsockopt(sk, PF_INET, optname, optval,
++ optlen);
+ #endif
+ return err;
+ }
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+@@ -259,15 +259,19 @@ getorigdst(struct sock *sk, int optval,
+ struct nf_conntrack_tuple tuple;
+
+ memset(&tuple, 0, sizeof(tuple));
++
++ lock_sock(sk);
+ tuple.src.u3.ip = inet->inet_rcv_saddr;
+ tuple.src.u.tcp.port = inet->inet_sport;
+ tuple.dst.u3.ip = inet->inet_daddr;
+ tuple.dst.u.tcp.port = inet->inet_dport;
+ tuple.src.l3num = PF_INET;
+ tuple.dst.protonum = sk->sk_protocol;
++ release_sock(sk);
+
+ /* We only do TCP and SCTP at the moment: is there a better way? */
+- if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP) {
++ if (tuple.dst.protonum != IPPROTO_TCP &&
++ tuple.dst.protonum != IPPROTO_SCTP) {
+ pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");
+ return -ENOPROTOOPT;
+ }
+--- a/net/ipv6/ipv6_sockglue.c
++++ b/net/ipv6/ipv6_sockglue.c
+@@ -905,12 +905,8 @@ int ipv6_setsockopt(struct sock *sk, int
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+ if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
+- optname != IPV6_XFRM_POLICY) {
+- lock_sock(sk);
+- err = nf_setsockopt(sk, PF_INET6, optname, optval,
+- optlen);
+- release_sock(sk);
+- }
++ optname != IPV6_XFRM_POLICY)
++ err = nf_setsockopt(sk, PF_INET6, optname, optval, optlen);
+ #endif
+ return err;
+ }
+@@ -940,12 +936,9 @@ int compat_ipv6_setsockopt(struct sock *
+ #ifdef CONFIG_NETFILTER
+ /* we need to exclude all possible ENOPROTOOPTs except default case */
+ if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
+- optname != IPV6_XFRM_POLICY) {
+- lock_sock(sk);
+- err = compat_nf_setsockopt(sk, PF_INET6, optname,
+- optval, optlen);
+- release_sock(sk);
+- }
++ optname != IPV6_XFRM_POLICY)
++ err = compat_nf_setsockopt(sk, PF_INET6, optname, optval,
++ optlen);
+ #endif
+ return err;
+ }
+--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+@@ -226,20 +226,27 @@ static struct nf_hook_ops ipv6_conntrack
+ static int
+ ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
+ {
+- const struct inet_sock *inet = inet_sk(sk);
++ struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
+ const struct ipv6_pinfo *inet6 = inet6_sk(sk);
++ const struct inet_sock *inet = inet_sk(sk);
+ const struct nf_conntrack_tuple_hash *h;
+ struct sockaddr_in6 sin6;
+- struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
+ struct nf_conn *ct;
++ __be32 flow_label;
++ int bound_dev_if;
+
++ lock_sock(sk);
+ tuple.src.u3.in6 = sk->sk_v6_rcv_saddr;
+ tuple.src.u.tcp.port = inet->inet_sport;
+ tuple.dst.u3.in6 = sk->sk_v6_daddr;
+ tuple.dst.u.tcp.port = inet->inet_dport;
+ tuple.dst.protonum = sk->sk_protocol;
++ bound_dev_if = sk->sk_bound_dev_if;
++ flow_label = inet6->flow_label;
++ release_sock(sk);
+
+- if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP)
++ if (tuple.dst.protonum != IPPROTO_TCP &&
++ tuple.dst.protonum != IPPROTO_SCTP)
+ return -ENOPROTOOPT;
+
+ if (*len < 0 || (unsigned int) *len < sizeof(sin6))
+@@ -257,14 +264,13 @@ ipv6_getorigdst(struct sock *sk, int opt
+
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
+- sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK;
++ sin6.sin6_flowinfo = flow_label & IPV6_FLOWINFO_MASK;
+ memcpy(&sin6.sin6_addr,
+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
+ sizeof(sin6.sin6_addr));
+
+ nf_ct_put(ct);
+- sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr,
+- sk->sk_bound_dev_if);
++ sin6.sin6_scope_id = ipv6_iface_scope_id(&sin6.sin6_addr, bound_dev_if);
+ return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
+ }
+
--- /dev/null
+From da17c73b6eb74aad3c3c0654394635675b623b3e Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 24 Jan 2018 17:16:09 -0800
+Subject: netfilter: x_tables: avoid out-of-bounds reads in xt_request_find_{match|target}
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit da17c73b6eb74aad3c3c0654394635675b623b3e upstream.
+
+It looks like syzbot found its way into netfilter territory.
+
+Issue here is that @name comes from user space and might
+not be null terminated.
+
+Out-of-bound reads happen, KASAN is not happy.
+
+v2 added similar fix for xt_request_find_target(),
+as Florian advised.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Acked-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/x_tables.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/netfilter/x_tables.c
++++ b/net/netfilter/x_tables.c
+@@ -206,6 +206,9 @@ xt_request_find_match(uint8_t nfproto, c
+ {
+ struct xt_match *match;
+
++ if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
++ return ERR_PTR(-EINVAL);
++
+ match = xt_find_match(nfproto, name, revision);
+ if (IS_ERR(match)) {
+ request_module("%st_%s", xt_prefix[nfproto], name);
+@@ -248,6 +251,9 @@ struct xt_target *xt_request_find_target
+ {
+ struct xt_target *target;
+
++ if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
++ return ERR_PTR(-EINVAL);
++
+ target = xt_find_target(af, name, revision);
+ if (IS_ERR(target)) {
+ request_module("%st_%s", xt_prefix[af], name);
--- /dev/null
+From 889c604fd0b5f6d3b8694ade229ee44124de1127 Mon Sep 17 00:00:00 2001
+From: Dmitry Vyukov <dvyukov@google.com>
+Date: Thu, 28 Dec 2017 09:48:54 +0100
+Subject: netfilter: x_tables: fix int overflow in xt_alloc_table_info()
+
+From: Dmitry Vyukov <dvyukov@google.com>
+
+commit 889c604fd0b5f6d3b8694ade229ee44124de1127 upstream.
+
+syzkaller triggered OOM kills by passing ipt_replace.size = -1
+to IPT_SO_SET_REPLACE. The root cause is that SMP_ALIGN() in
+xt_alloc_table_info() causes int overflow and the size check passes
+when it should not. SMP_ALIGN() is no longer needed leftover.
+
+Remove SMP_ALIGN() call in xt_alloc_table_info().
+
+Reported-by: syzbot+4396883fa8c4f64e0175@syzkaller.appspotmail.com
+Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/x_tables.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/net/netfilter/x_tables.c
++++ b/net/netfilter/x_tables.c
+@@ -38,8 +38,6 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
+
+-#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
+-
+ struct compat_delta {
+ unsigned int offset; /* offset in kernel */
+ int delta; /* delta in 32bit user land */
+@@ -954,7 +952,7 @@ struct xt_table_info *xt_alloc_table_inf
+ return NULL;
+
+ /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
+- if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
++ if ((size >> PAGE_SHIFT) + 2 > totalram_pages)
+ return NULL;
+
+ if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
--- /dev/null
+From 7dc68e98757a8eccf8ca7a53a29b896f1eef1f76 Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Mon, 5 Feb 2018 14:41:45 -0800
+Subject: netfilter: xt_RATEEST: acquire xt_rateest_mutex for hash insert
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+commit 7dc68e98757a8eccf8ca7a53a29b896f1eef1f76 upstream.
+
+rateest_hash is supposed to be protected by xt_rateest_mutex,
+and, as suggested by Eric, lookup and insert should be atomic,
+so we should acquire the xt_rateest_mutex once for both.
+
+So introduce a non-locking helper for internal use and keep the
+locking one for external.
+
+Reported-by: <syzbot+5cb189720978275e4c75@syzkaller.appspotmail.com>
+Fixes: 5859034d7eb8 ("[NETFILTER]: x_tables: add RATEEST target")
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/xt_RATEEST.c | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+--- a/net/netfilter/xt_RATEEST.c
++++ b/net/netfilter/xt_RATEEST.c
+@@ -40,23 +40,31 @@ static void xt_rateest_hash_insert(struc
+ hlist_add_head(&est->list, &rateest_hash[h]);
+ }
+
+-struct xt_rateest *xt_rateest_lookup(const char *name)
++static struct xt_rateest *__xt_rateest_lookup(const char *name)
+ {
+ struct xt_rateest *est;
+ unsigned int h;
+
+ h = xt_rateest_hash(name);
+- mutex_lock(&xt_rateest_mutex);
+ hlist_for_each_entry(est, &rateest_hash[h], list) {
+ if (strcmp(est->name, name) == 0) {
+ est->refcnt++;
+- mutex_unlock(&xt_rateest_mutex);
+ return est;
+ }
+ }
+- mutex_unlock(&xt_rateest_mutex);
++
+ return NULL;
+ }
++
++struct xt_rateest *xt_rateest_lookup(const char *name)
++{
++ struct xt_rateest *est;
++
++ mutex_lock(&xt_rateest_mutex);
++ est = __xt_rateest_lookup(name);
++ mutex_unlock(&xt_rateest_mutex);
++ return est;
++}
+ EXPORT_SYMBOL_GPL(xt_rateest_lookup);
+
+ void xt_rateest_put(struct xt_rateest *est)
+@@ -104,8 +112,10 @@ static int xt_rateest_tg_checkentry(cons
+ rnd_inited = true;
+ }
+
+- est = xt_rateest_lookup(info->name);
++ mutex_lock(&xt_rateest_mutex);
++ est = __xt_rateest_lookup(info->name);
+ if (est) {
++ mutex_unlock(&xt_rateest_mutex);
+ /*
+ * If estimator parameters are specified, they must match the
+ * existing estimator.
+@@ -143,11 +153,13 @@ static int xt_rateest_tg_checkentry(cons
+
+ info->est = est;
+ xt_rateest_hash_insert(est);
++ mutex_unlock(&xt_rateest_mutex);
+ return 0;
+
+ err2:
+ kfree(est);
+ err1:
++ mutex_unlock(&xt_rateest_mutex);
+ return ret;
+ }
+
--- /dev/null
+From f35157417215ec138c920320c746fdb3e04ef1d5 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Tue, 4 Jul 2017 17:25:02 +0100
+Subject: Provide a function to create a NUL-terminated string from unterminated data
+
+From: David Howells <dhowells@redhat.com>
+
+commit f35157417215ec138c920320c746fdb3e04ef1d5 upstream.
+
+Provide a function, kmemdup_nul(), that will create a NUL-terminated string
+from an unterminated character array where the length is known in advance.
+
+This is better than kstrndup() in situations where we already know the
+string length as the strnlen() in kstrndup() is superfluous.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/string.h | 1 +
+ mm/util.c | 24 ++++++++++++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+--- a/include/linux/string.h
++++ b/include/linux/string.h
+@@ -122,6 +122,7 @@ extern char *kstrdup(const char *s, gfp_
+ extern const char *kstrdup_const(const char *s, gfp_t gfp);
+ extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
+ extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
++extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
+
+ extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
+ extern void argv_free(char **argv);
+--- a/mm/util.c
++++ b/mm/util.c
+@@ -80,6 +80,8 @@ EXPORT_SYMBOL(kstrdup_const);
+ * @s: the string to duplicate
+ * @max: read at most @max chars from @s
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
++ *
++ * Note: Use kmemdup_nul() instead if the size is known exactly.
+ */
+ char *kstrndup(const char *s, size_t max, gfp_t gfp)
+ {
+@@ -118,6 +120,28 @@ void *kmemdup(const void *src, size_t le
+ EXPORT_SYMBOL(kmemdup);
+
+ /**
++ * kmemdup_nul - Create a NUL-terminated string from unterminated data
++ * @s: The data to stringify
++ * @len: The size of the data
++ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
++ */
++char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
++{
++ char *buf;
++
++ if (!s)
++ return NULL;
++
++ buf = kmalloc_track_caller(len + 1, gfp);
++ if (buf) {
++ memcpy(buf, s, len);
++ buf[len] = '\0';
++ }
++ return buf;
++}
++EXPORT_SYMBOL(kmemdup_nul);
++
++/**
+ * memdup_user - duplicate memory region from user space
+ *
+ * @src: source address in user space
--- /dev/null
+From ef28df55ac27e1e5cd122e19fa311d886d47a756 Mon Sep 17 00:00:00 2001
+From: Paul Moore <paul@paul-moore.com>
+Date: Tue, 28 Nov 2017 18:51:12 -0500
+Subject: selinux: ensure the context is NUL terminated in security_context_to_sid_core()
+
+From: Paul Moore <paul@paul-moore.com>
+
+commit ef28df55ac27e1e5cd122e19fa311d886d47a756 upstream.
+
+The syzbot/syzkaller automated tests found a problem in
+security_context_to_sid_core() during early boot (before we load the
+SELinux policy) where we could potentially feed context strings without
+NUL terminators into the strcmp() function.
+
+We already guard against this during normal operation (after the SELinux
+policy has been loaded) by making a copy of the context strings and
+explicitly adding a NUL terminator to the end. The patch extends this
+protection to the early boot case (no loaded policy) by moving the context
+copy earlier in security_context_to_sid_core().
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Reviewed-By: William Roberts <william.c.roberts@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/selinux/ss/services.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -1406,27 +1406,25 @@ static int security_context_to_sid_core(
+ if (!scontext_len)
+ return -EINVAL;
+
++ /* Copy the string to allow changes and ensure a NUL terminator */
++ scontext2 = kmemdup_nul(scontext, scontext_len, gfp_flags);
++ if (!scontext2)
++ return -ENOMEM;
++
+ if (!ss_initialized) {
+ int i;
+
+ for (i = 1; i < SECINITSID_NUM; i++) {
+- if (!strcmp(initial_sid_to_string[i], scontext)) {
++ if (!strcmp(initial_sid_to_string[i], scontext2)) {
+ *sid = i;
+- return 0;
++ goto out;
+ }
+ }
+ *sid = SECINITSID_KERNEL;
+- return 0;
++ goto out;
+ }
+ *sid = SECSID_NULL;
+
+- /* Copy the string so that we can modify the copy as we parse it. */
+- scontext2 = kmalloc(scontext_len + 1, gfp_flags);
+- if (!scontext2)
+- return -ENOMEM;
+- memcpy(scontext2, scontext, scontext_len);
+- scontext2[scontext_len] = 0;
+-
+ if (force) {
+ /* Save another copy for storing in uninterpreted form */
+ rc = -ENOMEM;
--- /dev/null
+From 4b14752ec4e0d87126e636384cf37c8dd9df157c Mon Sep 17 00:00:00 2001
+From: Paul Moore <paul@paul-moore.com>
+Date: Tue, 5 Dec 2017 17:17:43 -0500
+Subject: selinux: skip bounded transition processing if the policy isn't loaded
+
+From: Paul Moore <paul@paul-moore.com>
+
+commit 4b14752ec4e0d87126e636384cf37c8dd9df157c upstream.
+
+We can't do anything reasonable in security_bounded_transition() if we
+don't have a policy loaded, and in fact we could run into problems
+with some of the code inside expecting a policy. Fix these problems
+like we do many others in security/selinux/ss/services.c by checking
+to see if the policy is loaded (ss_initialized) and returning quickly
+if it isn't.
+
+Reported-by: syzbot <syzkaller-bugs@googlegroups.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Reviewed-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/selinux/ss/services.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -860,6 +860,9 @@ int security_bounded_transition(u32 old_
+ int index;
+ int rc;
+
++ if (!ss_initialized)
++ return 0;
++
+ read_lock(&policy_rwlock);
+
+ rc = -EINVAL;
--- /dev/null
+net-add-dst_cache-support.patch
+net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.patch
+cfg80211-check-dev_set_name-return-value.patch
+mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch
+xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch
+xfrm-check-id-proto-in-validate_tmpl.patch
+blktrace-fix-unlocked-registration-of-tracepoints.patch
+drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch
+provide-a-function-to-create-a-nul-terminated-string-from-unterminated-data.patch
+selinux-ensure-the-context-is-nul-terminated-in-security_context_to_sid_core.patch
+selinux-skip-bounded-transition-processing-if-the-policy-isn-t-loaded.patch
+crypto-x86-twofish-3way-fix-rbp-usage.patch
+staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch
+kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch
+netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch
+netfilter-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch
+netfilter-ipt_clusterip-fix-out-of-bounds-accesses-in-clusterip_tg_check.patch
+netfilter-on-sockopt-acquire-sock-lock-only-in-the-required-scope.patch
+netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.patch
+net-avoid-skb_warn_bad_offload-on-is_err.patch
--- /dev/null
+From 0c75f10312a35b149b2cebb1832316b35c2337ca Mon Sep 17 00:00:00 2001
+From: Laura Abbott <labbott@redhat.com>
+Date: Fri, 5 Jan 2018 11:14:08 -0800
+Subject: staging: android: ion: Add __GFP_NOWARN for system contig heap
+
+From: Laura Abbott <labbott@redhat.com>
+
+commit 0c75f10312a35b149b2cebb1832316b35c2337ca upstream.
+
+syzbot reported a warning from Ion:
+
+ WARNING: CPU: 1 PID: 3485 at mm/page_alloc.c:3926
+
+ ...
+ __alloc_pages_nodemask+0x9fb/0xd80 mm/page_alloc.c:4252
+ alloc_pages_current+0xb6/0x1e0 mm/mempolicy.c:2036
+ alloc_pages include/linux/gfp.h:492 [inline]
+ ion_system_contig_heap_allocate+0x40/0x2c0
+ drivers/staging/android/ion/ion_system_heap.c:374
+ ion_buffer_create drivers/staging/android/ion/ion.c:93 [inline]
+ ion_alloc+0x2c1/0x9e0 drivers/staging/android/ion/ion.c:420
+ ion_ioctl+0x26d/0x380 drivers/staging/android/ion/ion-ioctl.c:84
+ vfs_ioctl fs/ioctl.c:46 [inline]
+ do_vfs_ioctl+0x1b1/0x1520 fs/ioctl.c:686
+ SYSC_ioctl fs/ioctl.c:701 [inline]
+ SyS_ioctl+0x8f/0xc0 fs/ioctl.c:692
+
+This is a warning about attempting to allocate order > MAX_ORDER. This
+is coming from a userspace Ion allocation request. Since userspace is
+free to request however much memory it wants (and the kernel is free to
+deny its allocation), silence the allocation attempt with __GFP_NOWARN
+in case it fails.
+
+Reported-by: syzbot+76e7efc4748495855a4d@syzkaller.appspotmail.com
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Laura Abbott <labbott@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/android/ion/ion_system_heap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/android/ion/ion_system_heap.c
++++ b/drivers/staging/android/ion/ion_system_heap.c
+@@ -336,7 +336,7 @@ static int ion_system_contig_heap_alloca
+ if (align > (PAGE_SIZE << order))
+ return -EINVAL;
+
+- page = alloc_pages(low_order_gfp_flags, order);
++ page = alloc_pages(low_order_gfp_flags | __GFP_NOWARN, order);
+ if (!page)
+ return -ENOMEM;
+
--- /dev/null
+From 6a53b7593233ab9e4f96873ebacc0f653a55c3e1 Mon Sep 17 00:00:00 2001
+From: Cong Wang <xiyou.wangcong@gmail.com>
+Date: Mon, 27 Nov 2017 11:15:16 -0800
+Subject: xfrm: check id proto in validate_tmpl()
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+commit 6a53b7593233ab9e4f96873ebacc0f653a55c3e1 upstream.
+
+syzbot reported a kernel warning in xfrm_state_fini(), which
+indicates that we have entries left in the list
+net->xfrm.state_all whose proto is zero. And
+xfrm_id_proto_match() doesn't consider them as a match with
+IPSEC_PROTO_ANY in this case.
+
+Proto with value 0 is probably not a valid value, at least
+verify_newsa_info() doesn't consider it valid either.
+
+This patch fixes it by checking the proto value in
+validate_tmpl() and rejecting invalid ones, like what iproute2
+does in xfrm_xfrmproto_getbyname().
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/xfrm/xfrm_user.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1402,6 +1402,21 @@ static int validate_tmpl(int nr, struct
+ default:
+ return -EINVAL;
+ }
++
++ switch (ut[i].id.proto) {
++ case IPPROTO_AH:
++ case IPPROTO_ESP:
++ case IPPROTO_COMP:
++#if IS_ENABLED(CONFIG_IPV6)
++ case IPPROTO_ROUTING:
++ case IPPROTO_DSTOPTS:
++#endif
++ case IPSEC_PROTO_ANY:
++ break;
++ default:
++ return -EINVAL;
++ }
++
+ }
+
+ return 0;
--- /dev/null
+From ddc47e4404b58f03e98345398fb12d38fe291512 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Wed, 29 Nov 2017 06:53:55 +0100
+Subject: xfrm: Fix stack-out-of-bounds read on socket policy lookup.
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+commit ddc47e4404b58f03e98345398fb12d38fe291512 upstream.
+
+When we do tunnel or beet mode, we pass saddr and daddr from the
+template to xfrm_state_find(), this is ok. On transport mode,
+we pass the addresses from the flowi, assuming that the IP
+addresses (and address family) don't change during transformation.
+This assumption is wrong in the IPv4 mapped IPv6 case, packet
+is IPv4 and template is IPv6.
+
+Fix this by catching address family missmatches of the policy
+and the flow already before we do the lookup.
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/xfrm/xfrm_policy.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1225,9 +1225,15 @@ static struct xfrm_policy *xfrm_sk_polic
+ read_lock_bh(&net->xfrm.xfrm_policy_lock);
+ pol = rcu_dereference(sk->sk_policy[dir]);
+ if (pol != NULL) {
+- bool match = xfrm_selector_match(&pol->selector, fl, family);
++ bool match;
+ int err = 0;
+
++ if (pol->family != family) {
++ pol = NULL;
++ goto out;
++ }
++
++ match = xfrm_selector_match(&pol->selector, fl, family);
+ if (match) {
+ if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
+ pol = NULL;