diff -Naur -X exclude-files ac_cur/arch/um/include/user_util.h ac/arch/um/include/user_util.h --- ac_cur/arch/um/include/user_util.h Tue Aug 7 09:49:45 2001 +++ ac/arch/um/include/user_util.h Tue Aug 7 10:39:52 2001 @@ -60,7 +60,8 @@ extern __u64 file_size(char *file); extern void stop(void); extern int proc_start_thread(unsigned long ip, unsigned long sp); -extern void stack_protections(unsigned long address, int len); +extern void stack_protections(unsigned long address); +extern void task_protections(unsigned long address); extern void abandon_proc_space(int (*proc)(void *), unsigned long sp); extern int signals(int (*init_proc)(void *), void *sp); extern void map(unsigned long virt, void *p, unsigned long len, diff -Naur -X exclude-files ac_cur/arch/um/kernel/exec_kern.c ac/arch/um/kernel/exec_kern.c --- ac_cur/arch/um/kernel/exec_kern.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/exec_kern.c Tue Aug 7 10:39:52 2001 @@ -45,11 +45,19 @@ if((vma == NULL) || (vma->vm_start > addr)) force_sigbus(); } +/* See comment above fork_tramp for why sigstop is defined and used like + * this + */ + +static int sigstop = SIGSTOP; + static int exec_tramp(void *sig_stack) { + int sig = sigstop; + block_signals(); init_new_thread(sig_stack, NULL); - kill(getpid(), SIGSTOP); + kill(getpid(), sig); return(0); } @@ -71,9 +79,7 @@ current->thread.extern_pid = new_pid; free_page(stack); protect(physmem, high_physmem - physmem, 1, 1, 0); - stack = (unsigned long) current; - protect(stack + PAGE_SIZE, PAGE_SIZE, 0, 0, 0); - stack_protections(stack + 2 * PAGE_SIZE, 2 * PAGE_SIZE); + task_protections((unsigned long) current); force_flush_all(); check_brk(brk_start); unblock_signals(); diff -Naur -X exclude-files ac_cur/arch/um/kernel/ksyms.c ac/arch/um/kernel/ksyms.c --- ac_cur/arch/um/kernel/ksyms.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/ksyms.c Tue Aug 7 10:39:52 2001 @@ -4,6 +4,7 @@ #include "asm/delay.h" #include "asm/processor.h" #include "asm/unistd.h" +#include "asm/pgalloc.h" #include "kern_util.h" #include "user_util.h" @@ -18,3 +19,5 @@ EXPORT_SYMBOL(task_size); EXPORT_SYMBOL(__do_copy_from_user); EXPORT_SYMBOL(__do_strncpy_from_user); +EXPORT_SYMBOL(flush_tlb_range); +EXPORT_SYMBOL(__do_clear_user); diff -Naur -X exclude-files ac_cur/arch/um/kernel/process.c ac/arch/um/kernel/process.c --- ac_cur/arch/um/kernel/process.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/process.c Tue Aug 7 10:39:52 2001 @@ -102,11 +102,25 @@ init_irq_signals(sig_stack != NULL); } +/* This sigstop business works around a bug in gcc's -pg support. + * Normally a procedure's mcount call comes after esp has been copied to + * ebp and the new frame is constructed. With procedures with no locals, + * the mcount comes before, as the first thing that the procedure does. + * When that procedure is main for a thread, ebp comes in as NULL. So, + * when mcount dereferences it, it segfaults. So, UML works around this + * by adding a non-optimizable local to the various trampolines, fork_tramp + * and outer_tramp below, and exec_tramp. + */ + +static int sigstop = SIGSTOP; + int fork_tramp(void *sig_stack) { + int sig = sigstop; + block_signals(); init_new_thread(sig_stack, finish_fork_handler); - kill(getpid(), SIGSTOP); + kill(getpid(), sig); return(0); } @@ -118,15 +132,20 @@ int pid; }; +/* See above for why sigkill is here */ + +int sigkill = SIGKILL; + int outer_tramp(void *arg) { struct tramp *t; + int sig = sigkill; t = arg; t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, t->flags, (void *) t->stack); if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT); - kill(getpid(), SIGKILL); + kill(getpid(), sig); exit(0); } @@ -155,7 +174,7 @@ if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", errno); if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) - panic("outer trampoline didn't exit 0"); + panic("outer trampoline didn't exit with SIGKILL"); return(arg.pid); } diff -Naur -X exclude-files ac_cur/arch/um/kernel/process_kern.c ac/arch/um/kernel/process_kern.c --- ac_cur/arch/um/kernel/process_kern.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/process_kern.c Tue Aug 7 10:39:52 2001 @@ -123,7 +123,7 @@ if((page = __get_free_page(GFP_KERNEL)) == 0) panic("Couldn't allocate new stack"); - stack_protections(page, PAGE_SIZE); + stack_protections(page); return(page); } @@ -515,15 +515,11 @@ void finish_fork_handler(int sig) { - unsigned long stack; - init_flush_vm(); check_brk(brk_start); if(current->mm != current->p_pptr->mm) protect(physmem, high_physmem - physmem, 1, 1, 0); - stack = (unsigned long) current; - protect(stack + PAGE_SIZE, PAGE_SIZE, 0, 0, 0); - stack_protections(stack + 2 * PAGE_SIZE, 2 * PAGE_SIZE); + task_protections((unsigned long) current); if(current->thread.request.u.fork_finish.from) schedule_tail(current->thread.request.u.fork_finish.from); free_page(current->thread.request.u.fork_finish.stack); diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_user.c ac/arch/um/kernel/trap_user.c --- ac_cur/arch/um/kernel/trap_user.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/trap_user.c Tue Aug 7 10:39:52 2001 @@ -90,7 +90,7 @@ extern void signal_usr1(int sig); -int tracing_pid; +int tracing_pid = -1; int signals(int (*init_proc)(void *), void *sp) { diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c --- ac_cur/arch/um/kernel/um_arch.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/um_arch.c Tue Aug 7 10:40:37 2001 @@ -295,8 +295,7 @@ #ifndef CONFIG_SMP current = &init_task; #endif - protect(((unsigned long) &init_task) + PAGE_SIZE, PAGE_SIZE, 0, 0, 0); - stack_protections(init_task.thread.kernel_stack, 2 * PAGE_SIZE); + task_protections((unsigned long) &init_task); sp = (void *) init_task.thread.kernel_stack + 2 * PAGE_SIZE - sizeof(unsigned long); return(signals(start_kernel_proc, sp)); diff -Naur -X exclude-files ac_cur/arch/um/kernel/umid.c ac/arch/um/kernel/umid.c --- ac_cur/arch/um/kernel/umid.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/umid.c Tue Aug 7 10:39:52 2001 @@ -32,6 +32,8 @@ return(0); } +extern int tracing_pid; + static void create_pid_file(void) { char file[sizeof("/tmp/uml/") + UMID_LEN + sizeof("/pid\0")]; @@ -46,7 +48,7 @@ return; } - sprintf(pid, "%d\n", getpid()); + sprintf(pid, "%d\n", (tracing_pid == -1) ? getpid() : tracing_pid); if(write(fd, pid, strlen(pid)) != strlen(pid)) printk("Write of pid file failed - errno = %d\n", errno); close(fd); diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_util.c ac/arch/um/kernel/user_util.c --- ac_cur/arch/um/kernel/user_util.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/kernel/user_util.c Tue Aug 7 10:39:52 2001 @@ -172,9 +172,25 @@ while(1) sleep(1000000); } -void stack_protections(unsigned long address, int len) +void stack_protections(unsigned long address) { - mprotect((void *) address, len, PROT_READ | PROT_WRITE | PROT_EXEC); + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; + + if(mprotect((void *) address, page_size(), prot) < 0) + panic("protecting stack failed, errno = %d", errno); +} + +void task_protections(unsigned long address) +{ + unsigned long guard = address + page_size(); + unsigned long stack = guard + page_size(); + int prot = 0; + + if(mprotect((void *) stack, page_size(), prot) < 0) + panic("protecting guard page failed, errno = %d", errno); + prot = PROT_READ | PROT_WRITE | PROT_EXEC; + if(mprotect((void *) stack, 2 * page_size(), prot) < 0) + panic("protecting stack failed, errno = %d", errno); } void protect(unsigned long addr, unsigned long len, int r, int w, int x) @@ -183,10 +199,8 @@ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - if(mprotect((void *) addr, len, prot) == -1){ - perror("Protecting a page"); - panic("protect failed"); - } + if(mprotect((void *) addr, len, prot) == -1) + panic("protect failed, errno = %d", errno); } int wait_for_stop(int pid, int sig, int cont_type) diff -Naur -X exclude-files ac_cur/arch/um/ptproxy/sysdep.c ac/arch/um/ptproxy/sysdep.c --- ac_cur/arch/um/ptproxy/sysdep.c Tue Aug 7 09:49:45 2001 +++ ac/arch/um/ptproxy/sysdep.c Tue Aug 7 10:39:52 2001 @@ -7,6 +7,7 @@ #include #include +#include #include #include #include