From 6032aca0deb9c138df122192f8ef02de1fdccf25 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 14 Apr 2023 15:46:39 +0200 Subject: um: make stub data pages size tweakable There's a lot of code here that hard-codes that the data is a single page, and right now that seems to be sufficient, but to make it easier to change this in the future, add a new STUB_DATA_PAGES constant and use it throughout the code. Signed-off-by: Johannes Berg Signed-off-by: Richard Weinberger --- arch/um/include/shared/as-layout.h | 3 ++- arch/um/kernel/skas/clone.c | 5 +++-- arch/um/kernel/skas/mmu.c | 6 +++--- arch/um/kernel/um_arch.c | 10 +++++++--- arch/um/os-Linux/skas/process.c | 6 +++--- 5 files changed, 18 insertions(+), 12 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index 9a0bd648d872..9ec3015bc5e2 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h @@ -23,7 +23,8 @@ #define STUB_START stub_start #define STUB_CODE STUB_START #define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE) -#define STUB_END (STUB_DATA + UM_KERN_PAGE_SIZE) +#define STUB_DATA_PAGES 1 /* must be a power of two */ +#define STUB_END (STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index ff5061f29167..62435187dda4 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -24,11 +24,12 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { - struct stub_data *data = get_stub_page(); + struct stub_data *data = get_stub_data(); long err; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - (unsigned long)data + UM_KERN_PAGE_SIZE / 2); + (unsigned long)data + + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE / 2); if (err) { data->parent_err = err; goto done; diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 125df465e8ea..656fe16c9b63 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -21,7 +21,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) unsigned long stack = 0; int ret = -ENOMEM; - stack = get_zeroed_page(GFP_KERNEL); + stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO, ilog2(STUB_DATA_PAGES)); if (stack == 0) goto out; @@ -52,7 +52,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) out_free: if (to_mm->id.stack != 0) - free_page(to_mm->id.stack); + free_pages(to_mm->id.stack, ilog2(STUB_DATA_PAGES)); out: return ret; } @@ -74,6 +74,6 @@ void destroy_context(struct mm_struct *mm) } os_kill_ptraced_process(mmu->id.u.pid, 1); - free_page(mmu->id.stack); + free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES)); free_ldt(mmu); } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 8dcda617b8bf..0a23a98d4ca0 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -326,9 +326,13 @@ int __init linux_main(int argc, char **argv) add_arg(DEFAULT_COMMAND_LINE_CONSOLE); host_task_size = os_get_top_address(); - /* reserve two pages for the stubs */ - host_task_size -= 2 * PAGE_SIZE; - stub_start = host_task_size; + /* reserve a few pages for the stubs (taking care of data alignment) */ + /* align the data portion */ + BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES)); + stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1); + /* another page for the code portion */ + stub_start -= PAGE_SIZE; + host_task_size = stub_start; /* * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index b1ea53285af1..9464833e741a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -262,7 +262,7 @@ static int userspace_tramp(void *stack) if (stack != NULL) { fd = phys_mapping(uml_to_phys(stack), &offset); addr = mmap((void *) STUB_DATA, - UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, offset); if (addr == MAP_FAILED) { printk(UM_KERN_ERR "mapping segfault stack at 0x%lx failed, errno = %d\n", @@ -277,7 +277,7 @@ static int userspace_tramp(void *stack) (unsigned long) stub_segv_handler - (unsigned long) __syscall_stub_start; - set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); + set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; sa.sa_sigaction = (void *) v; @@ -515,7 +515,7 @@ static int __init init_thread_regs(void) thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) __syscall_stub_start; - thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - + thread_regs[REGS_SP_INDEX] = STUB_DATA + STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; -- cgit v1.2.3