| Gennady Sharapov | 60d339f | 2005-09-03 15:57:47 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 
|  | 3 | * Licensed under the GPL | 
|  | 4 | */ | 
|  | 5 |  | 
|  | 6 | #include <stdio.h> | 
|  | 7 | #include <unistd.h> | 
|  | 8 | #include <signal.h> | 
|  | 9 | #include <sched.h> | 
|  | 10 | #include <errno.h> | 
|  | 11 | #include <stdarg.h> | 
|  | 12 | #include <stdlib.h> | 
|  | 13 | #include <setjmp.h> | 
|  | 14 | #include <sys/time.h> | 
|  | 15 | #include <sys/ptrace.h> | 
|  | 16 | #include <linux/ptrace.h> | 
|  | 17 | #include <sys/wait.h> | 
|  | 18 | #include <sys/mman.h> | 
|  | 19 | #include <asm/ptrace.h> | 
|  | 20 | #include <asm/unistd.h> | 
|  | 21 | #include <asm/page.h> | 
|  | 22 | #include "user_util.h" | 
|  | 23 | #include "kern_util.h" | 
|  | 24 | #include "user.h" | 
|  | 25 | #include "signal_kern.h" | 
| Gennady Sharapov | 60d339f | 2005-09-03 15:57:47 -0700 | [diff] [blame] | 26 | #include "sysdep/ptrace.h" | 
|  | 27 | #include "sysdep/sigcontext.h" | 
|  | 28 | #include "irq_user.h" | 
|  | 29 | #include "ptrace_user.h" | 
| Gennady Sharapov | 60d339f | 2005-09-03 15:57:47 -0700 | [diff] [blame] | 30 | #include "init.h" | 
|  | 31 | #include "os.h" | 
|  | 32 | #include "uml-config.h" | 
|  | 33 | #include "choose-mode.h" | 
|  | 34 | #include "mode.h" | 
|  | 35 | #include "tempfile.h" | 
|  | 36 |  | 
| Jeff Dike | 0f80bc8 | 2005-09-16 19:27:50 -0700 | [diff] [blame] | 37 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, | 
|  | 38 | int must_succeed) | 
|  | 39 | { | 
|  | 40 | int err; | 
|  | 41 |  | 
|  | 42 | err = os_protect_memory((void *) addr, len, r, w, x); | 
|  | 43 | if(err < 0){ | 
|  | 44 | if(must_succeed) | 
|  | 45 | panic("protect failed, err = %d", -err); | 
|  | 46 | else return(err); | 
|  | 47 | } | 
|  | 48 | return(0); | 
|  | 49 | } | 
|  | 50 |  | 
| Gennady Sharapov | ea2ba7d | 2006-01-08 01:01:31 -0800 | [diff] [blame] | 51 | void kill_child_dead(int pid) | 
|  | 52 | { | 
|  | 53 | kill(pid, SIGKILL); | 
|  | 54 | kill(pid, SIGCONT); | 
|  | 55 | do { | 
|  | 56 | int n; | 
|  | 57 | CATCH_EINTR(n = waitpid(pid, NULL, 0)); | 
|  | 58 | if (n > 0) | 
|  | 59 | kill(pid, SIGCONT); | 
|  | 60 | else | 
|  | 61 | break; | 
|  | 62 | } while(1); | 
|  | 63 | } | 
|  | 64 |  | 
| Gennady Sharapov | 4fef0c1 | 2006-01-18 17:42:41 -0800 | [diff] [blame] | 65 | void stop(void) | 
|  | 66 | { | 
|  | 67 | while(1) sleep(1000000); | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | int wait_for_stop(int pid, int sig, int cont_type, void *relay) | 
|  | 71 | { | 
|  | 72 | sigset_t *relay_signals = relay; | 
|  | 73 | int status, ret; | 
|  | 74 |  | 
|  | 75 | while(1){ | 
|  | 76 | CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); | 
|  | 77 | if((ret < 0) || | 
|  | 78 | !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ | 
|  | 79 | if(ret < 0){ | 
|  | 80 | printk("wait failed, errno = %d\n", | 
|  | 81 | errno); | 
|  | 82 | } | 
|  | 83 | else if(WIFEXITED(status)) | 
|  | 84 | printk("process %d exited with status %d\n", | 
|  | 85 | pid, WEXITSTATUS(status)); | 
|  | 86 | else if(WIFSIGNALED(status)) | 
|  | 87 | printk("process %d exited with signal %d\n", | 
|  | 88 | pid, WTERMSIG(status)); | 
|  | 89 | else if((WSTOPSIG(status) == SIGVTALRM) || | 
|  | 90 | (WSTOPSIG(status) == SIGALRM) || | 
|  | 91 | (WSTOPSIG(status) == SIGIO) || | 
|  | 92 | (WSTOPSIG(status) == SIGPROF) || | 
|  | 93 | (WSTOPSIG(status) == SIGCHLD) || | 
|  | 94 | (WSTOPSIG(status) == SIGWINCH) || | 
|  | 95 | (WSTOPSIG(status) == SIGINT)){ | 
|  | 96 | ptrace(cont_type, pid, 0, WSTOPSIG(status)); | 
|  | 97 | continue; | 
|  | 98 | } | 
|  | 99 | else if((relay_signals != NULL) && | 
|  | 100 | sigismember(relay_signals, WSTOPSIG(status))){ | 
|  | 101 | ptrace(cont_type, pid, 0, WSTOPSIG(status)); | 
|  | 102 | continue; | 
|  | 103 | } | 
|  | 104 | else printk("process %d stopped with signal %d\n", | 
|  | 105 | pid, WSTOPSIG(status)); | 
|  | 106 | panic("wait_for_stop failed to wait for %d to stop " | 
|  | 107 | "with %d\n", pid, sig); | 
|  | 108 | } | 
|  | 109 | return(status); | 
|  | 110 | } | 
|  | 111 | } | 
|  | 112 |  | 
| Jeff Dike | 63ae2a9 | 2006-03-27 01:14:30 -0800 | [diff] [blame] | 113 | void forward_ipi(int fd, int pid) | 
|  | 114 | { | 
|  | 115 | int err; | 
|  | 116 |  | 
|  | 117 | err = os_set_owner(fd, pid); | 
|  | 118 | if(err < 0) | 
|  | 119 | printk("forward_ipi: set_owner failed, fd = %d, me = %d, " | 
|  | 120 | "target = %d, err = %d\n", fd, os_getpid(), pid, -err); | 
|  | 121 | } | 
|  | 122 |  | 
| Gennady Sharapov | 60d339f | 2005-09-03 15:57:47 -0700 | [diff] [blame] | 123 | /* | 
|  | 124 | *------------------------- | 
|  | 125 | * only for tt mode (will be deleted in future...) | 
|  | 126 | *------------------------- | 
|  | 127 | */ | 
|  | 128 |  | 
|  | 129 | struct tramp { | 
|  | 130 | int (*tramp)(void *); | 
|  | 131 | void *tramp_data; | 
|  | 132 | unsigned long temp_stack; | 
|  | 133 | int flags; | 
|  | 134 | int pid; | 
|  | 135 | }; | 
|  | 136 |  | 
|  | 137 | /* See above for why sigkill is here */ | 
|  | 138 |  | 
|  | 139 | int sigkill = SIGKILL; | 
|  | 140 |  | 
|  | 141 | int outer_tramp(void *arg) | 
|  | 142 | { | 
|  | 143 | struct tramp *t; | 
|  | 144 | int sig = sigkill; | 
|  | 145 |  | 
|  | 146 | t = arg; | 
|  | 147 | t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, | 
|  | 148 | t->flags, t->tramp_data); | 
|  | 149 | if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); | 
|  | 150 | kill(os_getpid(), sig); | 
|  | 151 | _exit(0); | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | int start_fork_tramp(void *thread_arg, unsigned long temp_stack, | 
|  | 155 | int clone_flags, int (*tramp)(void *)) | 
|  | 156 | { | 
|  | 157 | struct tramp arg; | 
|  | 158 | unsigned long sp; | 
|  | 159 | int new_pid, status, err; | 
|  | 160 |  | 
|  | 161 | /* The trampoline will run on the temporary stack */ | 
|  | 162 | sp = stack_sp(temp_stack); | 
|  | 163 |  | 
|  | 164 | clone_flags |= CLONE_FILES | SIGCHLD; | 
|  | 165 |  | 
|  | 166 | arg.tramp = tramp; | 
|  | 167 | arg.tramp_data = thread_arg; | 
|  | 168 | arg.temp_stack = temp_stack; | 
|  | 169 | arg.flags = clone_flags; | 
|  | 170 |  | 
|  | 171 | /* Start the process and wait for it to kill itself */ | 
|  | 172 | new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); | 
|  | 173 | if(new_pid < 0) | 
|  | 174 | return(new_pid); | 
|  | 175 |  | 
|  | 176 | CATCH_EINTR(err = waitpid(new_pid, &status, 0)); | 
|  | 177 | if(err < 0) | 
|  | 178 | panic("Waiting for outer trampoline failed - errno = %d", | 
|  | 179 | errno); | 
|  | 180 |  | 
|  | 181 | if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) | 
|  | 182 | panic("outer trampoline didn't exit with SIGKILL, " | 
|  | 183 | "status = %d", status); | 
|  | 184 |  | 
|  | 185 | return(arg.pid); | 
|  | 186 | } | 
|  | 187 |  | 
|  | 188 | void forward_pending_sigio(int target) | 
|  | 189 | { | 
|  | 190 | sigset_t sigs; | 
|  | 191 |  | 
|  | 192 | if(sigpending(&sigs)) | 
|  | 193 | panic("forward_pending_sigio : sigpending failed"); | 
|  | 194 | if(sigismember(&sigs, SIGIO)) | 
|  | 195 | kill(target, SIGIO); | 
|  | 196 | } | 
|  | 197 |  |