]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 Jun 2016 19:43:38 +0000 (12:43 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 Jun 2016 19:43:38 +0000 (12:43 -0700)
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

queue-4.6/batman-adv-fix-double-neigh_node_put-in-batadv_v_ogm_route_update.patch [new file with mode: 0644]
queue-4.6/mm-compaction.c-fix-zoneindex-in-kcompactd.patch [new file with mode: 0644]
queue-4.6/mm-use-phys_addr_t-for-reserve_bootmem_region-arguments.patch [new file with mode: 0644]
queue-4.6/qe-uart-add-fsl-t1040-ucc-uart-to-of_device_id.patch [new file with mode: 0644]
queue-4.6/series
queue-4.6/wait-ptrace-assume-__wall-if-the-child-is-traced.patch [new file with mode: 0644]

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 (file)
index 0000000..d0b01c8
--- /dev/null
@@ -0,0 +1,55 @@
+From a@unstable.cc  Sat Jun  4 12:37:07 2016
+From: Antonio Quartulli <a@unstable.cc>
+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 <sven@narfation.org>, Antonio Quartulli <a@unstable.cc>
+Message-ID: <20160521094817.401-1-a@unstable.cc>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+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 <sven@narfation.org>
+Signed-off-by: Antonio Quartulli <a@unstable.cc>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+
+
+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 (file)
index 0000000..db1f3dc
--- /dev/null
@@ -0,0 +1,56 @@
+From 6cd9dc3e75078ef646076fa63adfb9b85ced0b66 Mon Sep 17 00:00:00 2001
+From: Chen Feng <puck.chen@hisilicon.com>
+Date: Fri, 20 May 2016 16:59:02 -0700
+Subject: mm/compaction.c: fix zoneindex in kcompactd()
+
+From: Chen Feng <puck.chen@hisilicon.com>
+
+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 <puck.chen@hisilicon.com>
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Zhuangluan Su <suzhuangluan@hisilicon.com>
+Cc: Yiping Xu <xuyiping@hisilicon.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..7b14967
--- /dev/null
@@ -0,0 +1,57 @@
+From 4b50bcc7eda4d3cc9e3f2a0aa60e590fedf728c5 Mon Sep 17 00:00:00 2001
+From: Stefan Bader <stefan.bader@canonical.com>
+Date: Fri, 20 May 2016 16:58:38 -0700
+Subject: mm: use phys_addr_t for reserve_bootmem_region() arguments
+
+From: Stefan Bader <stefan.bader@canonical.com>
+
+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 <stefan.bader@canonical.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..63865fd
--- /dev/null
@@ -0,0 +1,31 @@
+From 11ca2b7ab432eb90906168c327733575e68d388f Mon Sep 17 00:00:00 2001
+From: Zhao Qiang <qiang.zhao@nxp.com>
+Date: Wed, 9 Mar 2016 09:48:11 +0800
+Subject: QE-UART: add "fsl,t1040-ucc-uart" to of_device_id
+
+From: Zhao Qiang <qiang.zhao@nxp.com>
+
+commit 11ca2b7ab432eb90906168c327733575e68d388f upstream.
+
+New bindings use "fsl,t1040-ucc-uart" as the compatible for qe-uart.
+So add it.
+
+Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index 52d8f713051f56fe8f8031a915d21e4de1e035d3..ae9428deea863dafc2f24071c64f630c4a12e5f0 100644 (file)
@@ -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 (file)
index 0000000..ab411c4
--- /dev/null
@@ -0,0 +1,126 @@
+From bf959931ddb88c4e4366e96dd22e68fa0db9527c Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Mon, 23 May 2016 16:23:50 -0700
+Subject: wait/ptrace: assume __WALL if the child is traced
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit bf959931ddb88c4e4366e96dd22e68fa0db9527c upstream.
+
+The following program (simplified version of generated by syzkaller)
+
+       #include <pthread.h>
+       #include <unistd.h>
+       #include <sys/ptrace.h>
+       #include <stdio.h>
+       #include <signal.h>
+
+       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 <oleg@redhat.com>
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: Jan Kratochvil <jan.kratochvil@redhat.com>
+Cc: "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com>
+Cc: Pedro Alves <palves@redhat.com>
+Cc: Roland McGrath <roland@hack.frob.com>
+Cc: <syzkaller@googlegroups.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;