2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-18 18:23:53 +08:00

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>
This commit is contained in:
Johannes Berg 2020-12-05 21:50:18 +01:00 committed by Richard Weinberger
parent 963285b0b4
commit ef4459a6da
4 changed files with 11 additions and 8 deletions
arch/um
drivers
include/shared
kernel
os-Linux

View File

@ -1241,7 +1241,7 @@ static int __init ubd_driver_init(void){
/* Letting ubd=sync be like using ubd#s= instead of ubd#= is /* Letting ubd=sync be like using ubd#s= instead of ubd#= is
* enough. So use anyway the io thread. */ * enough. So use anyway the io thread. */
} }
stack = alloc_stack(0, 0); stack = alloc_stack(0);
io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd); &thread_fd);
if(io_pid < 0){ if(io_pid < 0){

View File

@ -19,7 +19,7 @@ extern int kmalloc_ok;
#define UML_ROUND_UP(addr) \ #define UML_ROUND_UP(addr) \
((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK) ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
extern unsigned long alloc_stack(int order, int atomic); extern unsigned long alloc_stack(int atomic);
extern void free_stack(unsigned long stack, int order); extern void free_stack(unsigned long stack, int order);
struct pt_regs; struct pt_regs;

View File

@ -32,6 +32,7 @@
#include <os.h> #include <os.h>
#include <skas.h> #include <skas.h>
#include <linux/time-internal.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 * 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); 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; gfp_t flags = GFP_KERNEL;
if (atomic) if (atomic)
flags = GFP_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) static inline void set_current(struct task_struct *task)

View File

@ -45,7 +45,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
unsigned long stack, sp; unsigned long stack, sp;
int pid, fds[2], ret, n; int pid, fds[2], ret, n;
stack = alloc_stack(0, __cant_sleep()); stack = alloc_stack(__cant_sleep());
if (stack == 0) if (stack == 0)
return -ENOMEM; return -ENOMEM;
@ -116,7 +116,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long stack, sp; unsigned long stack, sp;
int pid, status, err; int pid, status, err;
stack = alloc_stack(0, __cant_sleep()); stack = alloc_stack(__cant_sleep());
if (stack == 0) if (stack == 0)
return -ENOMEM; return -ENOMEM;