summaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2020-12-05 21:50:18 +0100
committerRichard Weinberger <richard@nod.at>2020-12-13 22:38:06 +0100
commitef4459a6da0955b533ebfc97a7d756ac090f50c9 (patch)
tree5c1153080467c99b2f60942757f644d38338319b /arch/um/kernel
parentum: support some of ARCH_HAS_SET_MEMORY (diff)
downloadlinux-ef4459a6da0955b533ebfc97a7d756ac090f50c9.tar.xz
linux-ef4459a6da0955b533ebfc97a7d756ac090f50c9.zip
um: allocate a guard page to helper threads
We've been running into stack overflows in helper threads corrupting memory (e.g. because somebody put printf() or os_info() there), so to avoid those causing hard-to-debug issues later on, allocate a guard page for helper thread stacks and mark it read-only. Unfortunately, the crash dump at that point is useless as the stack tracer will try to backtrace the *kernel* thread, not the helper thread, but at least we don't survive to a random issue caused by corruption. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/process.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 81d508daf67c..2a986ece5478 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -32,6 +32,7 @@
#include <os.h>
#include <skas.h>
#include <linux/time-internal.h>
+#include <asm/set_memory.h>
/*
* This is a per-cpu array. A processor only modifies its entry and it only
@@ -62,16 +63,18 @@ void free_stack(unsigned long stack, int order)
free_pages(stack, order);
}
-unsigned long alloc_stack(int order, int atomic)
+unsigned long alloc_stack(int atomic)
{
- unsigned long page;
+ unsigned long addr;
gfp_t flags = GFP_KERNEL;
if (atomic)
flags = GFP_ATOMIC;
- page = __get_free_pages(flags, order);
+ addr = __get_free_pages(flags, 1);
- return page;
+ set_memory_ro(addr, 1);
+
+ return addr + PAGE_SIZE;
}
static inline void set_current(struct task_struct *task)