From 981955133bcee3e82b35200f37820613c092c937 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Feb 2018 19:23:40 +0100 Subject: [PATCH] 4.4-stable patches added patches: blktrace-fix-unlocked-registration-of-tracepoints.patch cfg80211-check-dev_set_name-return-value.patch crypto-x86-twofish-3way-fix-rbp-usage.patch drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch net-add-dst_cache-support.patch net-avoid-skb_warn_bad_offload-on-is_err.patch net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.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-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.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 staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch xfrm-check-id-proto-in-validate_tmpl.patch xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch --- ...unlocked-registration-of-tracepoints.patch | 144 +++++++ ...0211-check-dev_set_name-return-value.patch | 49 +++ ...rypto-x86-twofish-3way-fix-rbp-usage.patch | 260 ++++++++++++ ...-for-the-legacy-drm_modeset_lock_all.patch | 43 ++ ...-fix-escape-of-guest-dr6-to-the-host.patch | 68 ++++ ...er-no-op-if-register_shrinker-failed.patch | 110 +++++ queue-4.4/net-add-dst_cache-support.patch | 339 ++++++++++++++++ ...avoid-skb_warn_bad_offload-on-is_err.patch | 39 ++ ...-implementation-with-the-generic-one.patch | 376 ++++++++++++++++++ ...ounds-accesses-in-clusterip_tg_check.patch | 59 +++ ...sock-lock-only-in-the-required-scope.patch | 242 +++++++++++ ...ads-in-xt_request_find_-match-target.patch | 51 +++ ...-int-overflow-in-xt_alloc_table_info.patch | 45 +++ ...ire-xt_rateest_mutex-for-hash-insert.patch | 92 +++++ ...inated-string-from-unterminated-data.patch | 74 ++++ ...ated-in-security_context_to_sid_core.patch | 67 ++++ ...rocessing-if-the-policy-isn-t-loaded.patch | 38 ++ queue-4.4/series | 20 + ...-__gfp_nowarn-for-system-contig-heap.patch | 53 +++ ...xfrm-check-id-proto-in-validate_tmpl.patch | 57 +++ ...-bounds-read-on-socket-policy-lookup.patch | 46 +++ 21 files changed, 2272 insertions(+) create mode 100644 queue-4.4/blktrace-fix-unlocked-registration-of-tracepoints.patch create mode 100644 queue-4.4/cfg80211-check-dev_set_name-return-value.patch create mode 100644 queue-4.4/crypto-x86-twofish-3way-fix-rbp-usage.patch create mode 100644 queue-4.4/drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch create mode 100644 queue-4.4/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch create mode 100644 queue-4.4/mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch create mode 100644 queue-4.4/net-add-dst_cache-support.patch create mode 100644 queue-4.4/net-avoid-skb_warn_bad_offload-on-is_err.patch create mode 100644 queue-4.4/net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.patch create mode 100644 queue-4.4/netfilter-ipt_clusterip-fix-out-of-bounds-accesses-in-clusterip_tg_check.patch create mode 100644 queue-4.4/netfilter-on-sockopt-acquire-sock-lock-only-in-the-required-scope.patch create mode 100644 queue-4.4/netfilter-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch create mode 100644 queue-4.4/netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch create mode 100644 queue-4.4/netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.patch create mode 100644 queue-4.4/provide-a-function-to-create-a-nul-terminated-string-from-unterminated-data.patch create mode 100644 queue-4.4/selinux-ensure-the-context-is-nul-terminated-in-security_context_to_sid_core.patch create mode 100644 queue-4.4/selinux-skip-bounded-transition-processing-if-the-policy-isn-t-loaded.patch create mode 100644 queue-4.4/series create mode 100644 queue-4.4/staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch create mode 100644 queue-4.4/xfrm-check-id-proto-in-validate_tmpl.patch create mode 100644 queue-4.4/xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch diff --git a/queue-4.4/blktrace-fix-unlocked-registration-of-tracepoints.patch b/queue-4.4/blktrace-fix-unlocked-registration-of-tracepoints.patch new file mode 100644 index 00000000000..6653cb4bba6 --- /dev/null +++ b/queue-4.4/blktrace-fix-unlocked-registration-of-tracepoints.patch @@ -0,0 +1,144 @@ +From a6da0024ffc19e0d47712bb5ca4fd083f76b07df Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Sun, 5 Nov 2017 09:16:09 -0700 +Subject: blktrace: fix unlocked registration of tracepoints + +From: Jens Axboe + +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 +Tested-by: Dmitry Vyukov +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-4.4/cfg80211-check-dev_set_name-return-value.patch b/queue-4.4/cfg80211-check-dev_set_name-return-value.patch new file mode 100644 index 00000000000..55f0770a61a --- /dev/null +++ b/queue-4.4/cfg80211-check-dev_set_name-return-value.patch @@ -0,0 +1,49 @@ +From 59b179b48ce2a6076448a44531242ac2b3f6cef2 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 15 Jan 2018 09:58:27 +0100 +Subject: cfg80211: check dev_set_name() return value + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-4.4/crypto-x86-twofish-3way-fix-rbp-usage.patch b/queue-4.4/crypto-x86-twofish-3way-fix-rbp-usage.patch new file mode 100644 index 00000000000..f8b333a831e --- /dev/null +++ b/queue-4.4/crypto-x86-twofish-3way-fix-rbp-usage.patch @@ -0,0 +1,260 @@ +From d8c7fe9f2a486a6e5f0d5229ca43807af5ab22c6 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Mon, 18 Dec 2017 16:40:26 -0800 +Subject: crypto: x86/twofish-3way - Fix %rbp usage + +From: Eric Biggers + +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 +Signed-off-by: Eric Biggers +Reviewed-by: Josh Poimboeuf +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-4.4/drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch b/queue-4.4/drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch new file mode 100644 index 00000000000..bdec4c17d5f --- /dev/null +++ b/queue-4.4/drm-require-__gfp_nofail-for-the-legacy-drm_modeset_lock_all.patch @@ -0,0 +1,43 @@ +From d18d1a5ac811d12f7ebc1129230312b5f2c50cb8 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +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 + +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 +Cc: Daniel Vetter +Reported-by: syzbot +Signed-off-by: Daniel Vetter +Reviewed-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20171031115535.15166-1-chris@chris-wilson.co.uk +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-4.4/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch b/queue-4.4/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch new file mode 100644 index 00000000000..b61b4142aab --- /dev/null +++ b/queue-4.4/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch @@ -0,0 +1,68 @@ +From efdab992813fb2ed825745625b83c05032e9cda2 Mon Sep 17 00:00:00 2001 +From: Wanpeng Li +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 + +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 + + _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 +Cc: Paolo Bonzini +Cc: Radim Krčmář +Cc: David Hildenbrand +Cc: Dmitry Vyukov +Reviewed-by: David Hildenbrand +Signed-off-by: Wanpeng Li +Signed-off-by: Paolo Bonzini +Signed-off-by: Radim Krčmář +Signed-off-by: Greg Kroah-Hartman + +--- + 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, diff --git a/queue-4.4/mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch b/queue-4.4/mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch new file mode 100644 index 00000000000..62d69e6e48a --- /dev/null +++ b/queue-4.4/mm-vmscan-make-unregister_shrinker-no-op-if-register_shrinker-failed.patch @@ -0,0 +1,110 @@ +From bb422a738f6566f7439cd347d54e321e4fe92a9f Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Mon, 18 Dec 2017 20:31:41 +0900 +Subject: mm,vmscan: Make unregister_shrinker() no-op if register_shrinker() failed. + +From: Tetsuo Handa + +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 +Signed-off-by: Aliaksei Karaliou +Reported-by: syzbot +Cc: Glauber Costa +Cc: Al Viro +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-4.4/net-add-dst_cache-support.patch b/queue-4.4/net-add-dst_cache-support.patch new file mode 100644 index 00000000000..6b52b2d1fd6 --- /dev/null +++ b/queue-4.4/net-add-dst_cache-support.patch @@ -0,0 +1,339 @@ +From 911362c70df5b766c243dc297fadeaced786ffd8 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Fri, 12 Feb 2016 15:43:53 +0100 +Subject: net: add dst_cache support + +From: Paolo Abeni + +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: + + + + 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 +Suggested-and-acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Manoj Boopathi Raj +Signed-off-by: Greg Kroah-Hartman + +--- + 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 ++#include ++#if IS_ENABLED(CONFIG_IPV6) ++#include ++#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 ++ * ++ * 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 ++#include ++#include ++#include ++#if IS_ENABLED(CONFIG_IPV6) ++#include ++#endif ++#include ++ ++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); diff --git a/queue-4.4/net-avoid-skb_warn_bad_offload-on-is_err.patch b/queue-4.4/net-avoid-skb_warn_bad_offload-on-is_err.patch new file mode 100644 index 00000000000..ef8dbb4763a --- /dev/null +++ b/queue-4.4/net-avoid-skb_warn_bad_offload-on-is_err.patch @@ -0,0 +1,39 @@ +From 8d74e9f88d65af8bb2e095aff506aa6eac755ada Mon Sep 17 00:00:00 2001 +From: Willem de Bruijn +Date: Tue, 12 Dec 2017 11:39:04 -0500 +Subject: net: avoid skb_warn_bad_offload on IS_ERR + +From: Willem de Bruijn + +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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.4/net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.patch b/queue-4.4/net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.patch new file mode 100644 index 00000000000..d913e400e85 --- /dev/null +++ b/queue-4.4/net-replace-dst_cache-ip6_tunnel-implementation-with-the-generic-one.patch @@ -0,0 +1,376 @@ +From 607f725f6f7d5ec3759fbc16224afb60e2152a5b Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Fri, 12 Feb 2016 15:43:54 +0100 +Subject: net: replace dst_cache ip6_tunnel implementation with the generic one + +From: Paolo Abeni + +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: + + + dst = ip6_route_output(...) + + 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 +Suggested-and-acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Manoj Boopathi Raj +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include ++#include + + #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; + } diff --git a/queue-4.4/netfilter-ipt_clusterip-fix-out-of-bounds-accesses-in-clusterip_tg_check.patch b/queue-4.4/netfilter-ipt_clusterip-fix-out-of-bounds-accesses-in-clusterip_tg_check.patch new file mode 100644 index 00000000000..b114d0f1f51 --- /dev/null +++ b/queue-4.4/netfilter-ipt_clusterip-fix-out-of-bounds-accesses-in-clusterip_tg_check.patch @@ -0,0 +1,59 @@ +From 1a38956cce5eabd7b74f94bab70265e4df83165e Mon Sep 17 00:00:00 2001 +From: Dmitry Vyukov +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 + +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 +Reported-by: syzbot +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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) { diff --git a/queue-4.4/netfilter-on-sockopt-acquire-sock-lock-only-in-the-required-scope.patch b/queue-4.4/netfilter-on-sockopt-acquire-sock-lock-only-in-the-required-scope.patch new file mode 100644 index 00000000000..00cb1d9d661 --- /dev/null +++ b/queue-4.4/netfilter-on-sockopt-acquire-sock-lock-only-in-the-required-scope.patch @@ -0,0 +1,242 @@ +From 3f34cfae1238848fd53f25e5c8fd59da57901f4b Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Tue, 30 Jan 2018 19:01:40 +0100 +Subject: netfilter: on sockopt() acquire sock lock only in the required scope + +From: Paolo Abeni + +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 +Signed-off-by: Paolo Abeni +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-4.4/netfilter-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch b/queue-4.4/netfilter-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch new file mode 100644 index 00000000000..0622ef9475e --- /dev/null +++ b/queue-4.4/netfilter-x_tables-avoid-out-of-bounds-reads-in-xt_request_find_-match-target.patch @@ -0,0 +1,51 @@ +From da17c73b6eb74aad3c3c0654394635675b623b3e Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +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 + +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 +Reported-by: syzbot +Acked-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-4.4/netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch b/queue-4.4/netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch new file mode 100644 index 00000000000..737bc2611e5 --- /dev/null +++ b/queue-4.4/netfilter-x_tables-fix-int-overflow-in-xt_alloc_table_info.patch @@ -0,0 +1,45 @@ +From 889c604fd0b5f6d3b8694ade229ee44124de1127 Mon Sep 17 00:00:00 2001 +From: Dmitry Vyukov +Date: Thu, 28 Dec 2017 09:48:54 +0100 +Subject: netfilter: x_tables: fix int overflow in xt_alloc_table_info() + +From: Dmitry Vyukov + +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 +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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 "); + 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)) diff --git a/queue-4.4/netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.patch b/queue-4.4/netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.patch new file mode 100644 index 00000000000..3273a193049 --- /dev/null +++ b/queue-4.4/netfilter-xt_rateest-acquire-xt_rateest_mutex-for-hash-insert.patch @@ -0,0 +1,92 @@ +From 7dc68e98757a8eccf8ca7a53a29b896f1eef1f76 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Mon, 5 Feb 2018 14:41:45 -0800 +Subject: netfilter: xt_RATEEST: acquire xt_rateest_mutex for hash insert + +From: Cong Wang + +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: +Fixes: 5859034d7eb8 ("[NETFILTER]: x_tables: add RATEEST target") +Signed-off-by: Cong Wang +Reviewed-by: Florian Westphal +Reviewed-by: Eric Dumazet +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-4.4/provide-a-function-to-create-a-nul-terminated-string-from-unterminated-data.patch b/queue-4.4/provide-a-function-to-create-a-nul-terminated-string-from-unterminated-data.patch new file mode 100644 index 00000000000..4f90b8aa231 --- /dev/null +++ b/queue-4.4/provide-a-function-to-create-a-nul-terminated-string-from-unterminated-data.patch @@ -0,0 +1,74 @@ +From f35157417215ec138c920320c746fdb3e04ef1d5 Mon Sep 17 00:00:00 2001 +From: David Howells +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 + +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 +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-4.4/selinux-ensure-the-context-is-nul-terminated-in-security_context_to_sid_core.patch b/queue-4.4/selinux-ensure-the-context-is-nul-terminated-in-security_context_to_sid_core.patch new file mode 100644 index 00000000000..09c745cb0c8 --- /dev/null +++ b/queue-4.4/selinux-ensure-the-context-is-nul-terminated-in-security_context_to_sid_core.patch @@ -0,0 +1,67 @@ +From ef28df55ac27e1e5cd122e19fa311d886d47a756 Mon Sep 17 00:00:00 2001 +From: Paul Moore +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 + +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 +Signed-off-by: Paul Moore +Reviewed-By: William Roberts +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.4/selinux-skip-bounded-transition-processing-if-the-policy-isn-t-loaded.patch b/queue-4.4/selinux-skip-bounded-transition-processing-if-the-policy-isn-t-loaded.patch new file mode 100644 index 00000000000..2fe5ab833ff --- /dev/null +++ b/queue-4.4/selinux-skip-bounded-transition-processing-if-the-policy-isn-t-loaded.patch @@ -0,0 +1,38 @@ +From 4b14752ec4e0d87126e636384cf37c8dd9df157c Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Tue, 5 Dec 2017 17:17:43 -0500 +Subject: selinux: skip bounded transition processing if the policy isn't loaded + +From: Paul Moore + +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 +Signed-off-by: Paul Moore +Acked-by: Stephen Smalley +Reviewed-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..2d76b509950 --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,20 @@ +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 diff --git a/queue-4.4/staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch b/queue-4.4/staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch new file mode 100644 index 00000000000..985474559f5 --- /dev/null +++ b/queue-4.4/staging-android-ion-add-__gfp_nowarn-for-system-contig-heap.patch @@ -0,0 +1,53 @@ +From 0c75f10312a35b149b2cebb1832316b35c2337ca Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Fri, 5 Jan 2018 11:14:08 -0800 +Subject: staging: android: ion: Add __GFP_NOWARN for system contig heap + +From: Laura Abbott + +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 +Signed-off-by: Laura Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-4.4/xfrm-check-id-proto-in-validate_tmpl.patch b/queue-4.4/xfrm-check-id-proto-in-validate_tmpl.patch new file mode 100644 index 00000000000..aa2b953350e --- /dev/null +++ b/queue-4.4/xfrm-check-id-proto-in-validate_tmpl.patch @@ -0,0 +1,57 @@ +From 6a53b7593233ab9e4f96873ebacc0f653a55c3e1 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Mon, 27 Nov 2017 11:15:16 -0800 +Subject: xfrm: check id proto in validate_tmpl() + +From: Cong Wang + +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 +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Cong Wang +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.4/xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch b/queue-4.4/xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch new file mode 100644 index 00000000000..d2e8e3a3ee4 --- /dev/null +++ b/queue-4.4/xfrm-fix-stack-out-of-bounds-read-on-socket-policy-lookup.patch @@ -0,0 +1,46 @@ +From ddc47e4404b58f03e98345398fb12d38fe291512 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Wed, 29 Nov 2017 06:53:55 +0100 +Subject: xfrm: Fix stack-out-of-bounds read on socket policy lookup. + +From: Steffen Klassert + +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 +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman + +--- + 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; -- 2.47.3