From 8b0c0f86435a9719e309b8055988eec0cd6e8b4b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 4 Jun 2016 12:43:38 -0700 Subject: [PATCH] 4.6-stable patches added patches: batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch mm-compaction.c-fix-zoneindex-in-kcompactd.patch mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch wait-ptrace-assume-__wall-if-the-child-is-traced.patch --- ...ode_put-in-batadv_v_ogm_route_update.patch | 55 ++++++++ ...paction.c-fix-zoneindex-in-kcompactd.patch | 56 ++++++++ ...for-reserve_bootmem_region-arguments.patch | 57 ++++++++ ...d-fsl-t1040-ucc-uart-to-of_device_id.patch | 31 +++++ queue-4.6/series | 5 + ...assume-__wall-if-the-child-is-traced.patch | 126 ++++++++++++++++++ 6 files changed, 330 insertions(+) create mode 100644 queue-4.6/batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch create mode 100644 queue-4.6/mm-compaction.c-fix-zoneindex-in-kcompactd.patch create mode 100644 queue-4.6/mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch create mode 100644 queue-4.6/qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch create mode 100644 queue-4.6/wait-ptrace-assume-__wall-if-the-child-is-traced.patch diff --git a/queue-4.6/batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch b/queue-4.6/batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch new file mode 100644 index 00000000000..d0b01c83bd0 --- /dev/null +++ b/queue-4.6/batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch @@ -0,0 +1,55 @@ +From a@unstable.cc Sat Jun 4 12:37:07 2016 +From: Antonio Quartulli +Date: Sat, 21 May 2016 17:48:17 +0800 +Subject: batman-adv: Fix double neigh_node_put in batadv_v_ogm_route_update +To: stable@vger.kernel.org +Cc: b.a.t.m.a.n@lists.open-mesh.org, Sven Eckelmann , Antonio Quartulli +Message-ID: <20160521094817.401-1-a@unstable.cc> + +From: Sven Eckelmann + +The router is put down twice when it was non-NULL and either orig_ifinfo is +NULL afterwards or batman-adv receives a packet with the same sequence +number. This will end up in a use-after-free when the batadv_neigh_node is +removed because the reference counter ended up too early at 0. + +This patch is skipping netdev and is being sent directly to stable in +accordance with David S. Miller[1]. + +The reason is that this patch applies only on linux-4.6 and not on +linux-4.7/net because it was "accidentally" fixed by a refactoring +commit (more details in [2]). + +It addresses a reference imbalance which systematically leads to a +use-after-free and then a kernel crash. + +[1] https://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg15258.html +[2] https://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg15252.html + + +Fixes: 9323158ef9f4 ("batman-adv: OGMv2 - implement originators logic") +Signed-off-by: Sven Eckelmann +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + + +Cheers, + + net/batman-adv/bat_v_ogm.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -529,8 +529,10 @@ static void batadv_v_ogm_route_update(st + goto out; + } + +- if (router) ++ if (router) { + batadv_neigh_node_put(router); ++ router = NULL; ++ } + + /* Update routes, and check if the OGM is from the best next hop */ + batadv_v_ogm_orig_update(bat_priv, orig_node, neigh_node, ogm2, diff --git a/queue-4.6/mm-compaction.c-fix-zoneindex-in-kcompactd.patch b/queue-4.6/mm-compaction.c-fix-zoneindex-in-kcompactd.patch new file mode 100644 index 00000000000..db1f3dc8aa7 --- /dev/null +++ b/queue-4.6/mm-compaction.c-fix-zoneindex-in-kcompactd.patch @@ -0,0 +1,56 @@ +From 6cd9dc3e75078ef646076fa63adfb9b85ced0b66 Mon Sep 17 00:00:00 2001 +From: Chen Feng +Date: Fri, 20 May 2016 16:59:02 -0700 +Subject: mm/compaction.c: fix zoneindex in kcompactd() + +From: Chen Feng + +commit 6cd9dc3e75078ef646076fa63adfb9b85ced0b66 upstream. + +While testing the kcompactd in my platform 3G MEM only DMA ZONE. I +found the kcompactd never wakeup. It seems the zoneindex has already +minus 1 before. So the traverse here should be <=. + +It fixes a regression where kswapd could previously compact, but +kcompactd not. Not a crash fix though. + +[akpm@linux-foundation.org: fix kcompactd_do_work() as well, per Hugh] +Link: http://lkml.kernel.org/r/1463659121-84124-1-git-send-email-puck.chen@hisilicon.com +Fixes: accf62422b3a ("mm, kswapd: replace kswapd compaction with waking up kcompactd") +Signed-off-by: Chen Feng +Acked-by: Vlastimil Babka +Cc: Hugh Dickins +Cc: Michal Hocko +Cc: Kirill A. Shutemov +Cc: Johannes Weiner +Cc: Tejun Heo +Cc: Zhuangluan Su +Cc: Yiping Xu +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/compaction.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -1742,7 +1742,7 @@ static bool kcompactd_node_suitable(pg_d + struct zone *zone; + enum zone_type classzone_idx = pgdat->kcompactd_classzone_idx; + +- for (zoneid = 0; zoneid < classzone_idx; zoneid++) { ++ for (zoneid = 0; zoneid <= classzone_idx; zoneid++) { + zone = &pgdat->node_zones[zoneid]; + + if (!populated_zone(zone)) +@@ -1777,7 +1777,7 @@ static void kcompactd_do_work(pg_data_t + cc.classzone_idx); + count_vm_event(KCOMPACTD_WAKE); + +- for (zoneid = 0; zoneid < cc.classzone_idx; zoneid++) { ++ for (zoneid = 0; zoneid <= cc.classzone_idx; zoneid++) { + int status; + + zone = &pgdat->node_zones[zoneid]; diff --git a/queue-4.6/mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch b/queue-4.6/mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch new file mode 100644 index 00000000000..7b1496789e1 --- /dev/null +++ b/queue-4.6/mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch @@ -0,0 +1,57 @@ +From 4b50bcc7eda4d3cc9e3f2a0aa60e590fedf728c5 Mon Sep 17 00:00:00 2001 +From: Stefan Bader +Date: Fri, 20 May 2016 16:58:38 -0700 +Subject: mm: use phys_addr_t for reserve_bootmem_region() arguments + +From: Stefan Bader + +commit 4b50bcc7eda4d3cc9e3f2a0aa60e590fedf728c5 upstream. + +Since commit 92923ca3aace ("mm: meminit: only set page reserved in the +memblock region") the reserved bit is set on reserved memblock regions. +However start and end address are passed as unsigned long. This is only +32bit on i386, so it can end up marking the wrong pages reserved for +ranges at 4GB and above. + +This was observed on a 32bit Xen dom0 which was booted with initial +memory set to a value below 4G but allowing to balloon in memory +(dom0_mem=1024M for example). This would define a reserved bootmem +region for the additional memory (for example on a 8GB system there was +a reverved region covering the 4GB-8GB range). But since the addresses +were passed on as unsigned long, this was actually marking all pages +from 0 to 4GB as reserved. + +Fixes: 92923ca3aacef63 ("mm: meminit: only set page reserved in the memblock region") +Link: http://lkml.kernel.org/r/1463491221-10573-1-git-send-email-stefan.bader@canonical.com +Signed-off-by: Stefan Bader +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/mm.h | 2 +- + mm/page_alloc.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1782,7 +1782,7 @@ extern void free_highmem_page(struct pag + extern void adjust_managed_page_count(struct page *page, long count); + extern void mem_init_print_info(const char *str); + +-extern void reserve_bootmem_region(unsigned long start, unsigned long end); ++extern void reserve_bootmem_region(phys_addr_t start, phys_addr_t end); + + /* Free the reserved page into the buddy system, so it gets managed. */ + static inline void __free_reserved_page(struct page *page) +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1003,7 +1003,7 @@ static inline void init_reserved_page(un + * marks the pages PageReserved. The remaining valid pages are later + * sent to the buddy page allocator. + */ +-void __meminit reserve_bootmem_region(unsigned long start, unsigned long end) ++void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end) + { + unsigned long start_pfn = PFN_DOWN(start); + unsigned long end_pfn = PFN_UP(end); diff --git a/queue-4.6/qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch b/queue-4.6/qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch new file mode 100644 index 00000000000..63865fdc333 --- /dev/null +++ b/queue-4.6/qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch @@ -0,0 +1,31 @@ +From 11ca2b7ab432eb90906168c327733575e68d388f Mon Sep 17 00:00:00 2001 +From: Zhao Qiang +Date: Wed, 9 Mar 2016 09:48:11 +0800 +Subject: QE-UART: add "fsl,t1040-ucc-uart" to of_device_id + +From: Zhao Qiang + +commit 11ca2b7ab432eb90906168c327733575e68d388f upstream. + +New bindings use "fsl,t1040-ucc-uart" as the compatible for qe-uart. +So add it. + +Signed-off-by: Zhao Qiang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/ucc_uart.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/tty/serial/ucc_uart.c ++++ b/drivers/tty/serial/ucc_uart.c +@@ -1478,6 +1478,9 @@ static const struct of_device_id ucc_uar + .type = "serial", + .compatible = "ucc_uart", + }, ++ { ++ .compatible = "fsl,t1040-ucc-uart", ++ }, + {}, + }; + MODULE_DEVICE_TABLE(of, ucc_uart_match); diff --git a/queue-4.6/series b/queue-4.6/series index 52d8f713051..ae9428deea8 100644 --- a/queue-4.6/series +++ b/queue-4.6/series @@ -69,3 +69,8 @@ pinctrl-exynos5440-use-off-stack-memory-for-pinctrl_gpio_range.patch pci-disable-all-bar-sizing-for-devices-with-non-compliant-bars.patch media-v4l2-compat-ioctl32-fix-missing-reserved-field-copy-in-put_v4l2_create32.patch pkcs-7-fix-missing-break-on-oid_sha224-case.patch +mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch +mm-compaction.c-fix-zoneindex-in-kcompactd.patch +wait-ptrace-assume-__wall-if-the-child-is-traced.patch +qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch +batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch diff --git a/queue-4.6/wait-ptrace-assume-__wall-if-the-child-is-traced.patch b/queue-4.6/wait-ptrace-assume-__wall-if-the-child-is-traced.patch new file mode 100644 index 00000000000..ab411c47fbc --- /dev/null +++ b/queue-4.6/wait-ptrace-assume-__wall-if-the-child-is-traced.patch @@ -0,0 +1,126 @@ +From bf959931ddb88c4e4366e96dd22e68fa0db9527c Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 23 May 2016 16:23:50 -0700 +Subject: wait/ptrace: assume __WALL if the child is traced + +From: Oleg Nesterov + +commit bf959931ddb88c4e4366e96dd22e68fa0db9527c upstream. + +The following program (simplified version of generated by syzkaller) + + #include + #include + #include + #include + #include + + void *thread_func(void *arg) + { + ptrace(PTRACE_TRACEME, 0,0,0); + return 0; + } + + int main(void) + { + pthread_t thread; + + if (fork()) + return 0; + + while (getppid() != 1) + ; + + pthread_create(&thread, NULL, thread_func, NULL); + pthread_join(thread, NULL); + return 0; + } + +creates an unreapable zombie if /sbin/init doesn't use __WALL. + +This is not a kernel bug, at least in a sense that everything works as +expected: debugger should reap a traced sub-thread before it can reap the +leader, but without __WALL/__WCLONE do_wait() ignores sub-threads. + +Unfortunately, it seems that /sbin/init in most (all?) distributions +doesn't use it and we have to change the kernel to avoid the problem. +Note also that most init's use sys_waitid() which doesn't allow __WALL, so +the necessary user-space fix is not that trivial. + +This patch just adds the "ptrace" check into eligible_child(). To some +degree this matches the "tsk->ptrace" in exit_notify(), ->exit_signal is +mostly ignored when the tracee reports to debugger. Or WSTOPPED, the +tracer doesn't need to set this flag to wait for the stopped tracee. + +This obviously means the user-visible change: __WCLONE and __WALL no +longer have any meaning for debugger. And I can only hope that this won't +break something, but at least strace/gdb won't suffer. + +We could make a more conservative change. Say, we can take __WCLONE into +account, or !thread_group_leader(). But it would be nice to not +complicate these historical/confusing checks. + +Signed-off-by: Oleg Nesterov +Reported-by: Dmitry Vyukov +Cc: Denys Vlasenko +Cc: Jan Kratochvil +Cc: "Michael Kerrisk (man-pages)" +Cc: Pedro Alves +Cc: Roland McGrath +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/exit.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -918,17 +918,28 @@ static int eligible_pid(struct wait_opts + task_pid_type(p, wo->wo_type) == wo->wo_pid; + } + +-static int eligible_child(struct wait_opts *wo, struct task_struct *p) ++static int ++eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p) + { + if (!eligible_pid(wo, p)) + return 0; +- /* Wait for all children (clone and not) if __WALL is set; +- * otherwise, wait for clone children *only* if __WCLONE is +- * set; otherwise, wait for non-clone children *only*. (Note: +- * A "clone" child here is one that reports to its parent +- * using a signal other than SIGCHLD.) */ +- if (((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE)) +- && !(wo->wo_flags & __WALL)) ++ ++ /* ++ * Wait for all children (clone and not) if __WALL is set or ++ * if it is traced by us. ++ */ ++ if (ptrace || (wo->wo_flags & __WALL)) ++ return 1; ++ ++ /* ++ * Otherwise, wait for clone children *only* if __WCLONE is set; ++ * otherwise, wait for non-clone children *only*. ++ * ++ * Note: a "clone" child here is one that reports to its parent ++ * using a signal other than SIGCHLD, or a non-leader thread which ++ * we can only see if it is traced by us. ++ */ ++ if ((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE)) + return 0; + + return 1; +@@ -1300,7 +1311,7 @@ static int wait_consider_task(struct wai + if (unlikely(exit_state == EXIT_DEAD)) + return 0; + +- ret = eligible_child(wo, p); ++ ret = eligible_child(wo, ptrace, p); + if (!ret) + return ret; + -- 2.47.3