summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@windriver.com>2018-03-06 15:36:52 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2018-03-06 15:36:52 -0500
commit0431dbb9f8ae2db584787fc83af5bc59439b3c3e (patch)
treefce109ea2e1d5eb765de60f05dbadb1e025650d9
parent970f842fde372eba690f7a154635a67531cda804 (diff)
downloadlongterm-queue-4.8-0431dbb9f8ae2db584787fc83af5bc59439b3c3e.tar.gz
add stack patches
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r--queue/dma-api-Teach-the-DMA-from-stack-check-about-vmapped.patch108
-rw-r--r--queue/iommu-amd-Don-t-put-completion-wait-semaphore-on-sta.patch151
-rw-r--r--queue/kthread-Pin-the-stack-via-try_get_task_stack-put_tas.patch75
-rw-r--r--queue/lib-syscall-Pin-the-task-stack-in-collect_syscall.patch60
-rw-r--r--queue/mm-kmemleak-ensure-that-the-task-stack-is-not-freed-.patch52
-rw-r--r--queue/series21
-rw-r--r--queue/x86-dumpstack-Pin-the-target-stack-when-dumping-it.patch94
-rw-r--r--queue/x86-efi-Prevent-mixed-mode-boot-corruption-with-CONF.patch217
-rw-r--r--queue/x86-process-Pin-the-target-stack-in-get_wchan.patch78
9 files changed, 856 insertions, 0 deletions
diff --git a/queue/dma-api-Teach-the-DMA-from-stack-check-about-vmapped.patch b/queue/dma-api-Teach-the-DMA-from-stack-check-about-vmapped.patch
new file mode 100644
index 0000000..b308073
--- /dev/null
+++ b/queue/dma-api-Teach-the-DMA-from-stack-check-about-vmapped.patch
@@ -0,0 +1,108 @@
+From b4a0f533e5976cb1a79f31d6152e1d322d79b7f1 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 11 Aug 2016 02:35:22 -0700
+Subject: [PATCH] dma-api: Teach the "DMA-from-stack" check about vmapped
+ stacks
+
+commit b4a0f533e5976cb1a79f31d6152e1d322d79b7f1 upstream.
+
+If we're using CONFIG_VMAP_STACK=y and we manage to point an sg entry
+at the stack, then either the sg page will be in highmem or sg_virt()
+will return the direct-map alias. In neither case will the existing
+check_for_stack() implementation realize that it's a stack page.
+
+Fix it by explicitly checking for stack pages.
+
+This has no effect by itself. It's broken out for ease of review.
+
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/448460622731312298bf19dcbacb1606e75de7a9.1470907718.git.luto@kernel.org
+[ Minor edits. ]
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/lib/dma-debug.c b/lib/dma-debug.c
+index fcfa1939ac41..06f02f6aecd2 100644
+--- a/lib/dma-debug.c
++++ b/lib/dma-debug.c
+@@ -22,6 +22,7 @@
+ #include <linux/stacktrace.h>
+ #include <linux/dma-debug.h>
+ #include <linux/spinlock.h>
++#include <linux/vmalloc.h>
+ #include <linux/debugfs.h>
+ #include <linux/uaccess.h>
+ #include <linux/export.h>
+@@ -1164,11 +1165,32 @@ static void check_unmap(struct dma_debug_entry *ref)
+ put_hash_bucket(bucket, &flags);
+ }
+
+-static void check_for_stack(struct device *dev, void *addr)
++static void check_for_stack(struct device *dev,
++ struct page *page, size_t offset)
+ {
+- if (object_is_on_stack(addr))
+- err_printk(dev, NULL, "DMA-API: device driver maps memory from "
+- "stack [addr=%p]\n", addr);
++ void *addr;
++ struct vm_struct *stack_vm_area = task_stack_vm_area(current);
++
++ if (!stack_vm_area) {
++ /* Stack is direct-mapped. */
++ if (PageHighMem(page))
++ return;
++ addr = page_address(page) + offset;
++ if (object_is_on_stack(addr))
++ err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [addr=%p]\n", addr);
++ } else {
++ /* Stack is vmalloced. */
++ int i;
++
++ for (i = 0; i < stack_vm_area->nr_pages; i++) {
++ if (page != stack_vm_area->pages[i])
++ continue;
++
++ addr = (u8 *)current->stack + i * PAGE_SIZE + offset;
++ err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [probable addr=%p]\n", addr);
++ break;
++ }
++ }
+ }
+
+ static inline bool overlap(void *addr, unsigned long len, void *start, void *end)
+@@ -1291,10 +1313,11 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
+ if (map_single)
+ entry->type = dma_debug_single;
+
++ check_for_stack(dev, page, offset);
++
+ if (!PageHighMem(page)) {
+ void *addr = page_address(page) + offset;
+
+- check_for_stack(dev, addr);
+ check_for_illegal_area(dev, addr, size);
+ }
+
+@@ -1386,8 +1409,9 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ entry->sg_call_ents = nents;
+ entry->sg_mapped_ents = mapped_ents;
+
++ check_for_stack(dev, sg_page(s), s->offset);
++
+ if (!PageHighMem(sg_page(s))) {
+- check_for_stack(dev, sg_virt(s));
+ check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
+ }
+
+--
+2.15.0
+
diff --git a/queue/iommu-amd-Don-t-put-completion-wait-semaphore-on-sta.patch b/queue/iommu-amd-Don-t-put-completion-wait-semaphore-on-sta.patch
new file mode 100644
index 0000000..9f9e30b
--- /dev/null
+++ b/queue/iommu-amd-Don-t-put-completion-wait-semaphore-on-sta.patch
@@ -0,0 +1,151 @@
+From a3de0b63f25363f419fdf26144153dceb94981dd Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Wed, 14 Sep 2016 11:41:59 +0200
+Subject: [PATCH] iommu/amd: Don't put completion-wait semaphore on stack
+
+commit 4bf5beef578e46393f11eb69dda7d17a065e05ff upstream.
+
+The semaphore used by the AMD IOMMU to signal command
+completion lived on the stack until now, which was safe as
+the driver busy-waited on the semaphore with IRQs disabled,
+so the stack can't go away under the driver.
+
+But the recently introduced vmap-based stacks break this as
+the physical address of the semaphore can't be determinded
+easily anymore. The driver used the __pa() macro, but that
+only works in the direct-mapping. The result were
+Completion-Wait timeout errors seen by the IOMMU driver,
+breaking system boot.
+
+Since putting the semaphore on the stack is bad design
+anyway, move the semaphore into 'struct amd_iommu'. It is
+protected by the per-iommu lock and now in the direct
+mapping again. This fixes the Completion-Wait timeout errors
+and makes AMD IOMMU systems boot again with vmap-based
+stacks enabled.
+
+Reported-by: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
+index 2d1f9d4c020f..ca127b8c8fea 100644
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -940,15 +940,13 @@ static void build_inv_irt(struct iommu_cmd *cmd, u16 devid)
+ * Writes the command to the IOMMUs command buffer and informs the
+ * hardware about the new command.
+ */
+-static int iommu_queue_command_sync(struct amd_iommu *iommu,
+- struct iommu_cmd *cmd,
+- bool sync)
++static int __iommu_queue_command_sync(struct amd_iommu *iommu,
++ struct iommu_cmd *cmd,
++ bool sync)
+ {
+ u32 left, tail, head, next_tail;
+- unsigned long flags;
+
+ again:
+- spin_lock_irqsave(&iommu->lock, flags);
+
+ head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
+ tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
+@@ -957,15 +955,14 @@ again:
+
+ if (left <= 0x20) {
+ struct iommu_cmd sync_cmd;
+- volatile u64 sem = 0;
+ int ret;
+
+- build_completion_wait(&sync_cmd, (u64)&sem);
+- copy_cmd_to_buffer(iommu, &sync_cmd, tail);
++ iommu->cmd_sem = 0;
+
+- spin_unlock_irqrestore(&iommu->lock, flags);
++ build_completion_wait(&sync_cmd, (u64)&iommu->cmd_sem);
++ copy_cmd_to_buffer(iommu, &sync_cmd, tail);
+
+- if ((ret = wait_on_sem(&sem)) != 0)
++ if ((ret = wait_on_sem(&iommu->cmd_sem)) != 0)
+ return ret;
+
+ goto again;
+@@ -976,9 +973,21 @@ again:
+ /* We need to sync now to make sure all commands are processed */
+ iommu->need_sync = sync;
+
++ return 0;
++}
++
++static int iommu_queue_command_sync(struct amd_iommu *iommu,
++ struct iommu_cmd *cmd,
++ bool sync)
++{
++ unsigned long flags;
++ int ret;
++
++ spin_lock_irqsave(&iommu->lock, flags);
++ ret = __iommu_queue_command_sync(iommu, cmd, sync);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+
+- return 0;
++ return ret;
+ }
+
+ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+@@ -993,19 +1002,29 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
+ static int iommu_completion_wait(struct amd_iommu *iommu)
+ {
+ struct iommu_cmd cmd;
+- volatile u64 sem = 0;
++ unsigned long flags;
+ int ret;
+
+ if (!iommu->need_sync)
+ return 0;
+
+- build_completion_wait(&cmd, (u64)&sem);
+
+- ret = iommu_queue_command_sync(iommu, &cmd, false);
++ build_completion_wait(&cmd, (u64)&iommu->cmd_sem);
++
++ spin_lock_irqsave(&iommu->lock, flags);
++
++ iommu->cmd_sem = 0;
++
++ ret = __iommu_queue_command_sync(iommu, &cmd, false);
+ if (ret)
+- return ret;
++ goto out_unlock;
++
++ ret = wait_on_sem(&iommu->cmd_sem);
+
+- return wait_on_sem(&sem);
++out_unlock:
++ spin_unlock_irqrestore(&iommu->lock, flags);
++
++ return ret;
+ }
+
+ static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
+diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
+index caf5e3822715..9652848e3155 100644
+--- a/drivers/iommu/amd_iommu_types.h
++++ b/drivers/iommu/amd_iommu_types.h
+@@ -524,6 +524,8 @@ struct amd_iommu {
+ struct irq_domain *ir_domain;
+ struct irq_domain *msi_domain;
+ #endif
++
++ volatile u64 __aligned(8) cmd_sem;
+ };
+
+ #define ACPIHID_UID_LEN 256
+--
+2.15.0
+
diff --git a/queue/kthread-Pin-the-stack-via-try_get_task_stack-put_tas.patch b/queue/kthread-Pin-the-stack-via-try_get_task_stack-put_tas.patch
new file mode 100644
index 0000000..3bccea6
--- /dev/null
+++ b/queue/kthread-Pin-the-stack-via-try_get_task_stack-put_tas.patch
@@ -0,0 +1,75 @@
+From 4f20a35ad56f5ee15bbcc4e14966960647931940 Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Thu, 15 Sep 2016 22:45:44 -0700
+Subject: [PATCH] kthread: Pin the stack via
+ try_get_task_stack()/put_task_stack() in to_live_kthread() function
+
+commit 23196f2e5f5d810578a772785807dcdc2b9fdce9 upstream.
+
+get_task_struct(tsk) no longer pins tsk->stack so all users of
+to_live_kthread() should do try_get_task_stack/put_task_stack to protect
+"struct kthread" which lives on kthread's stack.
+
+TODO: Kill to_live_kthread(), perhaps we can even kill "struct kthread" too,
+and rework kthread_stop(), it can use task_work_add() to sync with the exiting
+kernel thread.
+
+Message-Id: <20160629180357.GA7178@redhat.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Jann Horn <jann@thejh.net>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/cb9b16bbc19d4aea4507ab0552e4644c1211d130.1474003868.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/kernel/kthread.c b/kernel/kthread.c
+index 850b255649a2..d982c65f1578 100644
+--- a/kernel/kthread.c
++++ b/kernel/kthread.c
+@@ -65,7 +65,7 @@ static inline struct kthread *to_kthread(struct task_struct *k)
+ static struct kthread *to_live_kthread(struct task_struct *k)
+ {
+ struct completion *vfork = ACCESS_ONCE(k->vfork_done);
+- if (likely(vfork))
++ if (likely(vfork) && try_get_task_stack(k))
+ return __to_kthread(vfork);
+ return NULL;
+ }
+@@ -427,8 +427,10 @@ void kthread_unpark(struct task_struct *k)
+ {
+ struct kthread *kthread = to_live_kthread(k);
+
+- if (kthread)
++ if (kthread) {
+ __kthread_unpark(k, kthread);
++ put_task_stack(k);
++ }
+ }
+ EXPORT_SYMBOL_GPL(kthread_unpark);
+
+@@ -457,6 +459,7 @@ int kthread_park(struct task_struct *k)
+ wait_for_completion(&kthread->parked);
+ }
+ }
++ put_task_stack(k);
+ ret = 0;
+ }
+ return ret;
+@@ -492,6 +495,7 @@ int kthread_stop(struct task_struct *k)
+ __kthread_unpark(k, kthread);
+ wake_up_process(k);
+ wait_for_completion(&kthread->exited);
++ put_task_stack(k);
+ }
+ ret = k->exit_code;
+ put_task_struct(k);
+--
+2.15.0
+
diff --git a/queue/lib-syscall-Pin-the-task-stack-in-collect_syscall.patch b/queue/lib-syscall-Pin-the-task-stack-in-collect_syscall.patch
new file mode 100644
index 0000000..dd86783
--- /dev/null
+++ b/queue/lib-syscall-Pin-the-task-stack-in-collect_syscall.patch
@@ -0,0 +1,60 @@
+From 92040c8c2cd1a408802bea57fb586ccbb7a59c15 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 15 Sep 2016 22:45:47 -0700
+Subject: [PATCH] lib/syscall: Pin the task stack in collect_syscall()
+
+commit aa1f1a639621672b68f654dc815a7d8298ff396f upstream.
+
+This will avoid a potential read-after-free if collect_syscall()
+(e.g. /proc/PID/syscall) is called on an exiting task.
+
+Reported-by: Jann Horn <jann@thejh.net>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/0bfd8e6d4729c97745d3781a29610a33d0a8091d.1474003868.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/lib/syscall.c b/lib/syscall.c
+index e30e03932480..63239e097b13 100644
+--- a/lib/syscall.c
++++ b/lib/syscall.c
+@@ -7,9 +7,19 @@ static int collect_syscall(struct task_struct *target, long *callno,
+ unsigned long args[6], unsigned int maxargs,
+ unsigned long *sp, unsigned long *pc)
+ {
+- struct pt_regs *regs = task_pt_regs(target);
+- if (unlikely(!regs))
++ struct pt_regs *regs;
++
++ if (!try_get_task_stack(target)) {
++ /* Task has no stack, so the task isn't in a syscall. */
++ *callno = -1;
++ return 0;
++ }
++
++ regs = task_pt_regs(target);
++ if (unlikely(!regs)) {
++ put_task_stack(target);
+ return -EAGAIN;
++ }
+
+ *sp = user_stack_pointer(regs);
+ *pc = instruction_pointer(regs);
+@@ -18,6 +28,7 @@ static int collect_syscall(struct task_struct *target, long *callno,
+ if (*callno != -1L && maxargs > 0)
+ syscall_get_arguments(target, regs, 0, maxargs, args);
+
++ put_task_stack(target);
+ return 0;
+ }
+
+--
+2.15.0
+
diff --git a/queue/mm-kmemleak-ensure-that-the-task-stack-is-not-freed-.patch b/queue/mm-kmemleak-ensure-that-the-task-stack-is-not-freed-.patch
new file mode 100644
index 0000000..a6e55bb
--- /dev/null
+++ b/queue/mm-kmemleak-ensure-that-the-task-stack-is-not-freed-.patch
@@ -0,0 +1,52 @@
+From 37df49f433bc3a11f5716fe65aaec5189c6402cb Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Thu, 27 Oct 2016 17:46:47 -0700
+Subject: [PATCH] mm: kmemleak: ensure that the task stack is not freed during
+ scanning
+
+commit 37df49f433bc3a11f5716fe65aaec5189c6402cb upstream.
+
+Commit 68f24b08ee89 ("sched/core: Free the stack early if
+CONFIG_THREAD_INFO_IN_TASK") may cause the task->stack to be freed
+during kmemleak_scan() execution, leading to either a NULL pointer fault
+(if task->stack is NULL) or kmemleak accessing already freed memory.
+
+This patch uses the new try_get_task_stack() API to ensure that the task
+stack is not freed during kmemleak stack scanning.
+
+Addresses https://bugzilla.kernel.org/show_bug.cgi?id=173901.
+
+Fixes: 68f24b08ee89 ("sched/core: Free the stack early if CONFIG_THREAD_INFO_IN_TASK")
+Link: http://lkml.kernel.org/r/1476266223-14325-1-git-send-email-catalin.marinas@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Reported-by: CAI Qian <caiqian@redhat.com>
+Tested-by: CAI Qian <caiqian@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: CAI Qian <caiqian@redhat.com>
+Cc: Hillf Danton <hillf.zj@alibaba-inc.com>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+diff --git a/mm/kmemleak.c b/mm/kmemleak.c
+index a5e453cf05c4..e5355a5b423f 100644
+--- a/mm/kmemleak.c
++++ b/mm/kmemleak.c
+@@ -1453,8 +1453,11 @@ static void kmemleak_scan(void)
+
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+- scan_block(task_stack_page(p), task_stack_page(p) +
+- THREAD_SIZE, NULL);
++ void *stack = try_get_task_stack(p);
++ if (stack) {
++ scan_block(stack, stack + THREAD_SIZE, NULL);
++ put_task_stack(p);
++ }
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+ }
+--
+2.15.0
+
diff --git a/queue/series b/queue/series
index 9aa0e96..5051e98 100644
--- a/queue/series
+++ b/queue/series
@@ -1,2 +1,23 @@
+# v4.9-rc1~160^2~60
+dma-api-Teach-the-DMA-from-stack-check-about-vmapped.patch
+# v4.9-rc1~160^2~21
+iommu-amd-Don-t-put-completion-wait-semaphore-on-sta.patch
+# v4.9-rc1~160^2~18
+kthread-Pin-the-stack-via-try_get_task_stack-put_tas.patch
+# v4.9-rc1~160^2~17
+x86-dumpstack-Pin-the-target-stack-when-dumping-it.patch
+# v4.9-rc1~160^2~16
+x86-process-Pin-the-target-stack-in-get_wchan.patch
+# v4.9-rc1~160^2~15
+lib-syscall-Pin-the-task-stack-in-collect_syscall.patch
+# v4.9-rc1~160^2~14
+# sched/core: Free the stack early if CONFIG_THREAD_INFO_IN_TASK
+
+# v4.9-rc3~24^2~9
+mm-kmemleak-ensure-that-the-task-stack-is-not-freed-.patch
+
+# v4.9-rc6~36^2
+x86-efi-Prevent-mixed-mode-boot-corruption-with-CONF.patch
+
# v4.14-rc7~7
assoc_array-Fix-a-buggy-node-splitting-case.patch
diff --git a/queue/x86-dumpstack-Pin-the-target-stack-when-dumping-it.patch b/queue/x86-dumpstack-Pin-the-target-stack-when-dumping-it.patch
new file mode 100644
index 0000000..811d2e7
--- /dev/null
+++ b/queue/x86-dumpstack-Pin-the-target-stack-when-dumping-it.patch
@@ -0,0 +1,94 @@
+From 8a567429ebb70da56eb63f05deee51d9328c5c00 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 15 Sep 2016 22:45:45 -0700
+Subject: [PATCH] x86/dumpstack: Pin the target stack when dumping it
+
+commit 1959a60182f48879635812a03a99c02231ea8677 upstream.
+
+Specifically, pin the stack in save_stack_trace_tsk() and
+show_trace_log_lvl().
+
+This will prevent a crash if the target task dies before or while
+dumping its stack once we start freeing task stacks early.
+
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Jann Horn <jann@thejh.net>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/cf0082cde65d1941a996d026f2b2cdbfaca17bfa.1474003868.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
+index 09675712eba8..8ad32dc94e8d 100644
+--- a/arch/x86/kernel/dumpstack_32.c
++++ b/arch/x86/kernel/dumpstack_32.c
+@@ -95,6 +95,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack;
+ int i;
+
++ if (!try_get_task_stack(task))
++ return;
++
+ if (sp == NULL) {
+ if (regs)
+ sp = (unsigned long *)regs->sp;
+@@ -118,6 +121,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ }
+ pr_cont("\n");
+ show_trace_log_lvl(task, regs, sp, bp, log_lvl);
++
++ put_task_stack(task);
+ }
+
+
+diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
+index 9ee4520ce83c..1bcdb164afd9 100644
+--- a/arch/x86/kernel/dumpstack_64.c
++++ b/arch/x86/kernel/dumpstack_64.c
+@@ -253,6 +253,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ int cpu;
+ int i;
+
++ if (!try_get_task_stack(task))
++ return;
++
+ preempt_disable();
+ cpu = smp_processor_id();
+
+@@ -303,6 +306,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+
+ pr_cont("\n");
+ show_trace_log_lvl(task, regs, sp, bp, log_lvl);
++
++ put_task_stack(task);
+ }
+
+ void show_regs(struct pt_regs *regs)
+diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
+index 4738f5e0f2ab..b3f32fbe3ba4 100644
+--- a/arch/x86/kernel/stacktrace.c
++++ b/arch/x86/kernel/stacktrace.c
+@@ -79,9 +79,14 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
+
+ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+ {
++ if (!try_get_task_stack(tsk))
++ return;
++
+ dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
++
++ put_task_stack(tsk);
+ }
+ EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
+
+--
+2.15.0
+
diff --git a/queue/x86-efi-Prevent-mixed-mode-boot-corruption-with-CONF.patch b/queue/x86-efi-Prevent-mixed-mode-boot-corruption-with-CONF.patch
new file mode 100644
index 0000000..0d649d8
--- /dev/null
+++ b/queue/x86-efi-Prevent-mixed-mode-boot-corruption-with-CONF.patch
@@ -0,0 +1,217 @@
+From f6697df36bdf0bf7fce984605c2918d4a7b4269f Mon Sep 17 00:00:00 2001
+From: Matt Fleming <matt@codeblueprint.co.uk>
+Date: Sat, 12 Nov 2016 21:04:24 +0000
+Subject: [PATCH] x86/efi: Prevent mixed mode boot corruption with
+ CONFIG_VMAP_STACK=y
+
+commit f6697df36bdf0bf7fce984605c2918d4a7b4269f upstream.
+
+Booting an EFI mixed mode kernel has been crashing since commit:
+
+ e37e43a497d5 ("x86/mm/64: Enable vmapped stacks (CONFIG_HAVE_ARCH_VMAP_STACK=y)")
+
+The user-visible effect in my test setup was the kernel being unable
+to find the root file system ramdisk. This was likely caused by silent
+memory or page table corruption.
+
+Enabling CONFIG_DEBUG_VIRTUAL=y immediately flagged the thunking code as
+abusing virt_to_phys() because it was passing addresses that were not
+part of the kernel direct mapping.
+
+Use the slow version instead, which correctly handles all memory
+regions by performing a page table walk.
+
+Suggested-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: linux-efi@vger.kernel.org
+Link: http://lkml.kernel.org/r/20161112210424.5157-3-matt@codeblueprint.co.uk
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
+index 58b0f801f66f..319148bd4b05 100644
+--- a/arch/x86/platform/efi/efi_64.c
++++ b/arch/x86/platform/efi/efi_64.c
+@@ -31,6 +31,7 @@
+ #include <linux/io.h>
+ #include <linux/reboot.h>
+ #include <linux/slab.h>
++#include <linux/ucs2_string.h>
+
+ #include <asm/setup.h>
+ #include <asm/page.h>
+@@ -211,6 +212,35 @@ void efi_sync_low_kernel_mappings(void)
+ memcpy(pud_efi, pud_k, sizeof(pud_t) * num_entries);
+ }
+
++/*
++ * Wrapper for slow_virt_to_phys() that handles NULL addresses.
++ */
++static inline phys_addr_t
++virt_to_phys_or_null_size(void *va, unsigned long size)
++{
++ bool bad_size;
++
++ if (!va)
++ return 0;
++
++ if (virt_addr_valid(va))
++ return virt_to_phys(va);
++
++ /*
++ * A fully aligned variable on the stack is guaranteed not to
++ * cross a page bounary. Try to catch strings on the stack by
++ * checking that 'size' is a power of two.
++ */
++ bad_size = size > PAGE_SIZE || !is_power_of_2(size);
++
++ WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
++
++ return slow_virt_to_phys(va);
++}
++
++#define virt_to_phys_or_null(addr) \
++ virt_to_phys_or_null_size((addr), sizeof(*(addr)))
++
+ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+ {
+ unsigned long pfn, text;
+@@ -494,8 +524,8 @@ static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+
+ spin_lock(&rtc_lock);
+
+- phys_tm = virt_to_phys(tm);
+- phys_tc = virt_to_phys(tc);
++ phys_tm = virt_to_phys_or_null(tm);
++ phys_tc = virt_to_phys_or_null(tc);
+
+ status = efi_thunk(get_time, phys_tm, phys_tc);
+
+@@ -511,7 +541,7 @@ static efi_status_t efi_thunk_set_time(efi_time_t *tm)
+
+ spin_lock(&rtc_lock);
+
+- phys_tm = virt_to_phys(tm);
++ phys_tm = virt_to_phys_or_null(tm);
+
+ status = efi_thunk(set_time, phys_tm);
+
+@@ -529,9 +559,9 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
+
+ spin_lock(&rtc_lock);
+
+- phys_enabled = virt_to_phys(enabled);
+- phys_pending = virt_to_phys(pending);
+- phys_tm = virt_to_phys(tm);
++ phys_enabled = virt_to_phys_or_null(enabled);
++ phys_pending = virt_to_phys_or_null(pending);
++ phys_tm = virt_to_phys_or_null(tm);
+
+ status = efi_thunk(get_wakeup_time, phys_enabled,
+ phys_pending, phys_tm);
+@@ -549,7 +579,7 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+
+ spin_lock(&rtc_lock);
+
+- phys_tm = virt_to_phys(tm);
++ phys_tm = virt_to_phys_or_null(tm);
+
+ status = efi_thunk(set_wakeup_time, enabled, phys_tm);
+
+@@ -558,6 +588,10 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+ return status;
+ }
+
++static unsigned long efi_name_size(efi_char16_t *name)
++{
++ return ucs2_strsize(name, EFI_VAR_NAME_LEN) + 1;
++}
+
+ static efi_status_t
+ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
+@@ -567,11 +601,11 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
+ u32 phys_name, phys_vendor, phys_attr;
+ u32 phys_data_size, phys_data;
+
+- phys_data_size = virt_to_phys(data_size);
+- phys_vendor = virt_to_phys(vendor);
+- phys_name = virt_to_phys(name);
+- phys_attr = virt_to_phys(attr);
+- phys_data = virt_to_phys(data);
++ phys_data_size = virt_to_phys_or_null(data_size);
++ phys_vendor = virt_to_phys_or_null(vendor);
++ phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
++ phys_attr = virt_to_phys_or_null(attr);
++ phys_data = virt_to_phys_or_null_size(data, *data_size);
+
+ status = efi_thunk(get_variable, phys_name, phys_vendor,
+ phys_attr, phys_data_size, phys_data);
+@@ -586,9 +620,9 @@ efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
+ u32 phys_name, phys_vendor, phys_data;
+ efi_status_t status;
+
+- phys_name = virt_to_phys(name);
+- phys_vendor = virt_to_phys(vendor);
+- phys_data = virt_to_phys(data);
++ phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
++ phys_vendor = virt_to_phys_or_null(vendor);
++ phys_data = virt_to_phys_or_null_size(data, data_size);
+
+ /* If data_size is > sizeof(u32) we've got problems */
+ status = efi_thunk(set_variable, phys_name, phys_vendor,
+@@ -605,9 +639,9 @@ efi_thunk_get_next_variable(unsigned long *name_size,
+ efi_status_t status;
+ u32 phys_name_size, phys_name, phys_vendor;
+
+- phys_name_size = virt_to_phys(name_size);
+- phys_vendor = virt_to_phys(vendor);
+- phys_name = virt_to_phys(name);
++ phys_name_size = virt_to_phys_or_null(name_size);
++ phys_vendor = virt_to_phys_or_null(vendor);
++ phys_name = virt_to_phys_or_null_size(name, *name_size);
+
+ status = efi_thunk(get_next_variable, phys_name_size,
+ phys_name, phys_vendor);
+@@ -621,7 +655,7 @@ efi_thunk_get_next_high_mono_count(u32 *count)
+ efi_status_t status;
+ u32 phys_count;
+
+- phys_count = virt_to_phys(count);
++ phys_count = virt_to_phys_or_null(count);
+ status = efi_thunk(get_next_high_mono_count, phys_count);
+
+ return status;
+@@ -633,7 +667,7 @@ efi_thunk_reset_system(int reset_type, efi_status_t status,
+ {
+ u32 phys_data;
+
+- phys_data = virt_to_phys(data);
++ phys_data = virt_to_phys_or_null_size(data, data_size);
+
+ efi_thunk(reset_system, reset_type, status, data_size, phys_data);
+ }
+@@ -661,9 +695,9 @@ efi_thunk_query_variable_info(u32 attr, u64 *storage_space,
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+- phys_storage = virt_to_phys(storage_space);
+- phys_remaining = virt_to_phys(remaining_space);
+- phys_max = virt_to_phys(max_variable_size);
++ phys_storage = virt_to_phys_or_null(storage_space);
++ phys_remaining = virt_to_phys_or_null(remaining_space);
++ phys_max = virt_to_phys_or_null(max_variable_size);
+
+ status = efi_thunk(query_variable_info, attr, phys_storage,
+ phys_remaining, phys_max);
+--
+2.15.0
+
diff --git a/queue/x86-process-Pin-the-target-stack-in-get_wchan.patch b/queue/x86-process-Pin-the-target-stack-in-get_wchan.patch
new file mode 100644
index 0000000..550411f
--- /dev/null
+++ b/queue/x86-process-Pin-the-target-stack-in-get_wchan.patch
@@ -0,0 +1,78 @@
+From 57d2b47069f4fb80f0736f9101a5899b361bb18f Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 15 Sep 2016 22:45:46 -0700
+Subject: [PATCH] x86/process: Pin the target stack in get_wchan()
+
+commit 74327a3e884a0ff895ba7b51d3488e6a177407b2 upstream.
+
+This will prevent a crash if get_wchan() runs after the task stack
+is freed.
+
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Brian Gerst <brgerst@gmail.com>
+Cc: Denys Vlasenko <dvlasenk@redhat.com>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Cc: Jann Horn <jann@thejh.net>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/337aeca8614024aa4d8d9c81053bbf8fcffbe4ad.1474003868.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
+index 8089f4955bbc..26c7ffa8190c 100644
+--- a/arch/x86/kernel/process.c
++++ b/arch/x86/kernel/process.c
+@@ -520,15 +520,18 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
+ */
+ unsigned long get_wchan(struct task_struct *p)
+ {
+- unsigned long start, bottom, top, sp, fp, ip;
++ unsigned long start, bottom, top, sp, fp, ip, ret = 0;
+ int count = 0;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
++ if (!try_get_task_stack(p))
++ return 0;
++
+ start = (unsigned long)task_stack_page(p);
+ if (!start)
+- return 0;
++ goto out;
+
+ /*
+ * Layout of the stack page:
+@@ -552,16 +555,21 @@ unsigned long get_wchan(struct task_struct *p)
+
+ sp = READ_ONCE(p->thread.sp);
+ if (sp < bottom || sp > top)
+- return 0;
++ goto out;
+
+ fp = READ_ONCE_NOCHECK(((struct inactive_task_frame *)sp)->bp);
+ do {
+ if (fp < bottom || fp > top)
+- return 0;
++ goto out;
+ ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
+- if (!in_sched_functions(ip))
+- return ip;
++ if (!in_sched_functions(ip)) {
++ ret = ip;
++ goto out;
++ }
+ fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
+ } while (count++ < 16 && p->state != TASK_RUNNING);
+- return 0;
++
++out:
++ put_task_stack(p);
++ return ret;
+ }
+--
+2.15.0
+