diff options
| -rw-r--r-- | arch/um/os-Linux/skas/process.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 31c9be2c2bdd..819d68656673 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
| @@ -108,7 +108,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) | |||
| 108 | wait_stub_done(pid); | 108 | wait_stub_done(pid); |
| 109 | 109 | ||
| 110 | /* | 110 | /* |
| 111 | * faultinfo is prepared by the stub-segv-handler at start of | 111 | * faultinfo is prepared by the stub_segv_handler at start of |
| 112 | * the stub stack page. We just have to copy it. | 112 | * the stub stack page. We just have to copy it. |
| 113 | */ | 113 | */ |
| 114 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | 114 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); |
| @@ -175,6 +175,21 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, | |||
| 175 | 175 | ||
| 176 | extern char __syscall_stub_start[]; | 176 | extern char __syscall_stub_start[]; |
| 177 | 177 | ||
| 178 | /** | ||
| 179 | * userspace_tramp() - userspace trampoline | ||
| 180 | * @stack: pointer to the new userspace stack page, can be NULL, if? FIXME: | ||
| 181 | * | ||
| 182 | * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed. | ||
| 183 | * This function will run on a temporary stack page. | ||
| 184 | * It ptrace()'es itself, then | ||
| 185 | * Two pages are mapped into the userspace address space: | ||
| 186 | * - STUB_CODE (with EXEC), which contains the skas stub code | ||
| 187 | * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel. | ||
| 188 | * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process. | ||
| 189 | * And last the process stops itself to give control to the UML kernel for this userspace process. | ||
| 190 | * | ||
| 191 | * Return: Always zero, otherwise the current userspace process is ended with non null exit() call | ||
| 192 | */ | ||
| 178 | static int userspace_tramp(void *stack) | 193 | static int userspace_tramp(void *stack) |
| 179 | { | 194 | { |
| 180 | void *addr; | 195 | void *addr; |
| @@ -236,12 +251,24 @@ static int userspace_tramp(void *stack) | |||
| 236 | 251 | ||
| 237 | int userspace_pid[NR_CPUS]; | 252 | int userspace_pid[NR_CPUS]; |
| 238 | 253 | ||
| 254 | /** | ||
| 255 | * start_userspace() - prepare a new userspace process | ||
| 256 | * @stub_stack: pointer to the stub stack. Can be NULL, if? FIXME: | ||
| 257 | * | ||
| 258 | * Setups a new temporary stack page that is used while userspace_tramp() runs | ||
| 259 | * Clones the kernel process into a new userspace process, with FDs only. | ||
| 260 | * | ||
| 261 | * Return: When positive: the process id of the new userspace process, | ||
| 262 | * when negative: an error number. | ||
| 263 | * FIXME: can PIDs become negative?! | ||
| 264 | */ | ||
| 239 | int start_userspace(unsigned long stub_stack) | 265 | int start_userspace(unsigned long stub_stack) |
| 240 | { | 266 | { |
| 241 | void *stack; | 267 | void *stack; |
| 242 | unsigned long sp; | 268 | unsigned long sp; |
| 243 | int pid, status, n, flags, err; | 269 | int pid, status, n, flags, err; |
| 244 | 270 | ||
| 271 | /* setup a temporary stack page */ | ||
| 245 | stack = mmap(NULL, UM_KERN_PAGE_SIZE, | 272 | stack = mmap(NULL, UM_KERN_PAGE_SIZE, |
| 246 | PROT_READ | PROT_WRITE | PROT_EXEC, | 273 | PROT_READ | PROT_WRITE | PROT_EXEC, |
| 247 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 274 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| @@ -252,10 +279,12 @@ int start_userspace(unsigned long stub_stack) | |||
| 252 | return err; | 279 | return err; |
| 253 | } | 280 | } |
| 254 | 281 | ||
| 282 | /* set stack pointer to the end of the stack page, so it can grow downwards */ | ||
| 255 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); | 283 | sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); |
| 256 | 284 | ||
| 257 | flags = CLONE_FILES | SIGCHLD; | 285 | flags = CLONE_FILES | SIGCHLD; |
| 258 | 286 | ||
| 287 | /* clone into new userspace process */ | ||
| 259 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | 288 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); |
| 260 | if (pid < 0) { | 289 | if (pid < 0) { |
| 261 | err = -errno; | 290 | err = -errno; |
