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:
parent
963285b0b4
commit
ef4459a6da
arch/um
@ -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){
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user