1 /* 2 * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) 3 * Licensed under the GPL 4 */ 5 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <errno.h> 10 #include <signal.h> 11 #include <sched.h> 12 #include "ptrace_user.h" 13 #include <sys/wait.h> 14 #include <sys/mman.h> 15 #include <sys/user.h> 16 #include <sys/time.h> 17 #include <sys/syscall.h> 18 #include <asm/types.h> 19 #include "user.h" 20 #include "sysdep/ptrace.h" 21 #include "user_util.h" 22 #include "kern_util.h" 23 #include "skas.h" 24 #include "stub-data.h" 25 #include "mm_id.h" 26 #include "sysdep/sigcontext.h" 27 #include "sysdep/stub.h" 28 #include "os.h" 29 #include "proc_mm.h" 30 #include "skas_ptrace.h" 31 #include "chan_user.h" 32 #include "registers.h" 33 #include "mem.h" 34 #include "uml-config.h" 35 #include "process.h" 36 #include "longjmp.h" 37 38 int is_skas_winch(int pid, int fd, void *data) 39 { 40 if(pid != os_getpgrp()) 41 return(0); 42 43 register_winch_irq(-1, fd, -1, data); 44 return(1); 45 } 46 47 void wait_stub_done(int pid, int sig, char * fname) 48 { 49 int n, status, err; 50 51 do { 52 if ( sig != -1 ) { 53 err = ptrace(PTRACE_CONT, pid, 0, sig); 54 if(err) 55 panic("%s : continue failed, errno = %d\n", 56 fname, errno); 57 } 58 sig = 0; 59 60 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 61 } while((n >= 0) && WIFSTOPPED(status) && 62 ((WSTOPSIG(status) == SIGVTALRM) || 63 /* running UML inside a detached screen can cause 64 * SIGWINCHes 65 */ 66 (WSTOPSIG(status) == SIGWINCH))); 67 68 if((n < 0) || !WIFSTOPPED(status) || 69 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 70 unsigned long regs[HOST_FRAME_SIZE]; 71 72 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 73 printk("Failed to get registers from stub, " 74 "errno = %d\n", errno); 75 else { 76 int i; 77 78 printk("Stub registers -\n"); 79 for(i = 0; i < HOST_FRAME_SIZE; i++) 80 printk("\t%d - %lx\n", i, regs[i]); 81 } 82 panic("%s : failed to wait for SIGUSR1/SIGTRAP, " 83 "pid = %d, n = %d, errno = %d, status = 0x%x\n", 84 fname, pid, n, errno, status); 85 } 86 } 87 88 extern unsigned long current_stub_stack(void); 89 90 void get_skas_faultinfo(int pid, struct faultinfo * fi) 91 { 92 int err; 93 94 if(ptrace_faultinfo){ 95 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 96 if(err) 97 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " 98 "errno = %d\n", errno); 99 100 /* Special handling for i386, which has different structs */ 101 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 102 memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, 103 sizeof(struct faultinfo) - 104 sizeof(struct ptrace_faultinfo)); 105 } 106 else { 107 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); 108 109 /* faultinfo is prepared by the stub-segv-handler at start of 110 * the stub stack page. We just have to copy it. 111 */ 112 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); 113 } 114 } 115 116 static void handle_segv(int pid, union uml_pt_regs * regs) 117 { 118 get_skas_faultinfo(pid, ®s->skas.faultinfo); 119 segv(regs->skas.faultinfo, 0, 1, NULL); 120 } 121 122 /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ 123 static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) 124 { 125 int err, status; 126 127 /* Mark this as a syscall */ 128 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); 129 130 if (!local_using_sysemu) 131 { 132 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, 133 __NR_getpid); 134 if(err < 0) 135 panic("handle_trap - nullifying syscall failed errno = %d\n", 136 errno); 137 138 err = ptrace(PTRACE_SYSCALL, pid, 0, 0); 139 if(err < 0) 140 panic("handle_trap - continuing to end of syscall failed, " 141 "errno = %d\n", errno); 142 143 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 144 if((err < 0) || !WIFSTOPPED(status) || 145 (WSTOPSIG(status) != SIGTRAP + 0x80)) 146 panic("handle_trap - failed to wait at end of syscall, " 147 "errno = %d, status = %d\n", errno, status); 148 } 149 150 handle_syscall(regs); 151 } 152 153 extern int __syscall_stub_start; 154 155 static int userspace_tramp(void *stack) 156 { 157 void *addr; 158 int err; 159 160 ptrace(PTRACE_TRACEME, 0, 0, 0); 161 162 init_new_thread_signals(); 163 err = set_interval(1); 164 if(err) 165 panic("userspace_tramp - setting timer failed, errno = %d\n", 166 err); 167 168 if(!proc_mm){ 169 /* This has a pte, but it can't be mapped in with the usual 170 * tlb_flush mechanism because this is part of that mechanism 171 */ 172 int fd; 173 __u64 offset; 174 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 175 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), 176 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 177 if(addr == MAP_FAILED){ 178 printk("mapping mmap stub failed, errno = %d\n", 179 errno); 180 exit(1); 181 } 182 183 if(stack != NULL){ 184 fd = phys_mapping(to_phys(stack), &offset); 185 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), 186 PROT_READ | PROT_WRITE, 187 MAP_FIXED | MAP_SHARED, fd, offset); 188 if(addr == MAP_FAILED){ 189 printk("mapping segfault stack failed, " 190 "errno = %d\n", errno); 191 exit(1); 192 } 193 } 194 } 195 if(!ptrace_faultinfo && (stack != NULL)){ 196 struct sigaction sa; 197 198 unsigned long v = UML_CONFIG_STUB_CODE + 199 (unsigned long) stub_segv_handler - 200 (unsigned long) &__syscall_stub_start; 201 202 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); 203 sigemptyset(&sa.sa_mask); 204 sigaddset(&sa.sa_mask, SIGIO); 205 sigaddset(&sa.sa_mask, SIGWINCH); 206 sigaddset(&sa.sa_mask, SIGALRM); 207 sigaddset(&sa.sa_mask, SIGVTALRM); 208 sigaddset(&sa.sa_mask, SIGUSR1); 209 sa.sa_flags = SA_ONSTACK; 210 sa.sa_handler = (void *) v; 211 sa.sa_restorer = NULL; 212 if(sigaction(SIGSEGV, &sa, NULL) < 0) 213 panic("userspace_tramp - setting SIGSEGV handler " 214 "failed - errno = %d\n", errno); 215 } 216 217 os_stop_process(os_getpid()); 218 return(0); 219 } 220 221 /* Each element set once, and only accessed by a single processor anyway */ 222 #undef NR_CPUS 223 #define NR_CPUS 1 224 int userspace_pid[NR_CPUS]; 225 226 int start_userspace(unsigned long stub_stack) 227 { 228 void *stack; 229 unsigned long sp; 230 int pid, status, n, flags; 231 232 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, 233 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 234 if(stack == MAP_FAILED) 235 panic("start_userspace : mmap failed, errno = %d", errno); 236 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); 237 238 flags = CLONE_FILES | SIGCHLD; 239 if(proc_mm) flags |= CLONE_VM; 240 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 241 if(pid < 0) 242 panic("start_userspace : clone failed, errno = %d", errno); 243 244 do { 245 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 246 if(n < 0) 247 panic("start_userspace : wait failed, errno = %d", 248 errno); 249 } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); 250 251 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 252 panic("start_userspace : expected SIGSTOP, got status = %d", 253 status); 254 255 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) 256 panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", 257 errno); 258 259 if(munmap(stack, PAGE_SIZE) < 0) 260 panic("start_userspace : munmap failed, errno = %d\n", errno); 261 262 return(pid); 263 } 264 265 void userspace(union uml_pt_regs *regs) 266 { 267 int err, status, op, pid = userspace_pid[0]; 268 int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ 269 270 while(1){ 271 restore_registers(pid, regs); 272 273 /* Now we set local_using_sysemu to be used for one loop */ 274 local_using_sysemu = get_using_sysemu(); 275 276 op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); 277 278 err = ptrace(op, pid, 0, 0); 279 if(err) 280 panic("userspace - could not resume userspace process, " 281 "pid=%d, ptrace operation = %d, errno = %d\n", 282 pid, op, errno); 283 284 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 285 if(err < 0) 286 panic("userspace - waitpid failed, errno = %d\n", 287 errno); 288 289 regs->skas.is_user = 1; 290 save_registers(pid, regs); 291 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 292 293 if(WIFSTOPPED(status)){ 294 switch(WSTOPSIG(status)){ 295 case SIGSEGV: 296 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) 297 user_signal(SIGSEGV, regs, pid); 298 else handle_segv(pid, regs); 299 break; 300 case SIGTRAP + 0x80: 301 handle_trap(pid, regs, local_using_sysemu); 302 break; 303 case SIGTRAP: 304 relay_signal(SIGTRAP, regs); 305 break; 306 case SIGIO: 307 case SIGVTALRM: 308 case SIGILL: 309 case SIGBUS: 310 case SIGFPE: 311 case SIGWINCH: 312 user_signal(WSTOPSIG(status), regs, pid); 313 break; 314 default: 315 printk("userspace - child stopped with signal " 316 "%d\n", WSTOPSIG(status)); 317 } 318 pid = userspace_pid[0]; 319 interrupt_end(); 320 321 /* Avoid -ERESTARTSYS handling in host */ 322 if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) 323 PT_SYSCALL_NR(regs->skas.regs) = -1; 324 } 325 } 326 } 327 328 int copy_context_skas0(unsigned long new_stack, int pid) 329 { 330 int err; 331 unsigned long regs[HOST_FRAME_SIZE]; 332 unsigned long fp_regs[HOST_FP_SIZE]; 333 unsigned long current_stack = current_stub_stack(); 334 struct stub_data *data = (struct stub_data *) current_stack; 335 struct stub_data *child_data = (struct stub_data *) new_stack; 336 __u64 new_offset; 337 int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); 338 339 /* prepare offset and fd of child's stack as argument for parent's 340 * and child's mmap2 calls 341 */ 342 *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), 343 .fd = new_fd, 344 .timer = ((struct itimerval) 345 { { 0, 1000000 / hz() }, 346 { 0, 1000000 / hz() }})}); 347 get_safe_registers(regs, fp_regs); 348 349 /* Set parent's instruction pointer to start of clone-stub */ 350 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + 351 (unsigned long) stub_clone_handler - 352 (unsigned long) &__syscall_stub_start; 353 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - 354 sizeof(void *); 355 #ifdef __SIGNAL_FRAMESIZE 356 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; 357 #endif 358 err = ptrace_setregs(pid, regs); 359 if(err < 0) 360 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 361 "pid = %d, errno = %d\n", pid, -err); 362 363 err = ptrace_setfpregs(pid, fp_regs); 364 if(err < 0) 365 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " 366 "pid = %d, errno = %d\n", pid, -err); 367 368 /* set a well known return code for detection of child write failure */ 369 child_data->err = 12345678; 370 371 /* Wait, until parent has finished its work: read child's pid from 372 * parent's stack, and check, if bad result. 373 */ 374 wait_stub_done(pid, 0, "copy_context_skas0"); 375 376 pid = data->err; 377 if(pid < 0) 378 panic("copy_context_skas0 - stub-parent reports error %d\n", 379 -pid); 380 381 /* Wait, until child has finished too: read child's result from 382 * child's stack and check it. 383 */ 384 wait_stub_done(pid, -1, "copy_context_skas0"); 385 if (child_data->err != UML_CONFIG_STUB_DATA) 386 panic("copy_context_skas0 - stub-child reports error %ld\n", 387 child_data->err); 388 389 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, 390 (void *)PTRACE_O_TRACESYSGOOD) < 0) 391 panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " 392 "errno = %d\n", errno); 393 394 return pid; 395 } 396 397 /* 398 * This is used only, if stub pages are needed, while proc_mm is 399 * availabl. Opening /proc/mm creates a new mm_context, which lacks 400 * the stub-pages. Thus, we map them using /proc/mm-fd 401 */ 402 void map_stub_pages(int fd, unsigned long code, 403 unsigned long data, unsigned long stack) 404 { 405 struct proc_mm_op mmop; 406 int n; 407 __u64 code_offset; 408 int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), 409 &code_offset); 410 411 mmop = ((struct proc_mm_op) { .op = MM_MMAP, 412 .u = 413 { .mmap = 414 { .addr = code, 415 .len = PAGE_SIZE, 416 .prot = PROT_EXEC, 417 .flags = MAP_FIXED | MAP_PRIVATE, 418 .fd = code_fd, 419 .offset = code_offset 420 } } }); 421 n = os_write_file(fd, &mmop, sizeof(mmop)); 422 if(n != sizeof(mmop)){ 423 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", 424 code, code_fd, (unsigned long long) code_offset); 425 panic("map_stub_pages : /proc/mm map for code failed, " 426 "err = %d\n", -n); 427 } 428 429 if ( stack ) { 430 __u64 map_offset; 431 int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); 432 mmop = ((struct proc_mm_op) 433 { .op = MM_MMAP, 434 .u = 435 { .mmap = 436 { .addr = data, 437 .len = PAGE_SIZE, 438 .prot = PROT_READ | PROT_WRITE, 439 .flags = MAP_FIXED | MAP_SHARED, 440 .fd = map_fd, 441 .offset = map_offset 442 } } }); 443 n = os_write_file(fd, &mmop, sizeof(mmop)); 444 if(n != sizeof(mmop)) 445 panic("map_stub_pages : /proc/mm map for data failed, " 446 "err = %d\n", -n); 447 } 448 } 449 450 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 451 { 452 (*buf)[0].JB_IP = (unsigned long) handler; 453 (*buf)[0].JB_SP = (unsigned long) stack + 454 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); 455 } 456 457 #define INIT_JMP_NEW_THREAD 0 458 #define INIT_JMP_CALLBACK 1 459 #define INIT_JMP_HALT 2 460 #define INIT_JMP_REBOOT 3 461 462 void switch_threads(jmp_buf *me, jmp_buf *you) 463 { 464 if(UML_SETJMP(me) == 0) 465 UML_LONGJMP(you, 1); 466 } 467 468 static jmp_buf initial_jmpbuf; 469 470 /* XXX Make these percpu */ 471 static void (*cb_proc)(void *arg); 472 static void *cb_arg; 473 static jmp_buf *cb_back; 474 475 int start_idle_thread(void *stack, jmp_buf *switch_buf) 476 { 477 int n; 478 479 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 480 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 481 SIGVTALRM, -1); 482 483 n = UML_SETJMP(&initial_jmpbuf); 484 switch(n){ 485 case INIT_JMP_NEW_THREAD: 486 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; 487 (*switch_buf)[0].JB_SP = (unsigned long) stack + 488 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - 489 sizeof(void *); 490 break; 491 case INIT_JMP_CALLBACK: 492 (*cb_proc)(cb_arg); 493 UML_LONGJMP(cb_back, 1); 494 break; 495 case INIT_JMP_HALT: 496 kmalloc_ok = 0; 497 return(0); 498 case INIT_JMP_REBOOT: 499 kmalloc_ok = 0; 500 return(1); 501 default: 502 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 503 } 504 UML_LONGJMP(switch_buf, 1); 505 } 506 507 void initial_thread_cb_skas(void (*proc)(void *), void *arg) 508 { 509 jmp_buf here; 510 511 cb_proc = proc; 512 cb_arg = arg; 513 cb_back = &here; 514 515 block_signals(); 516 if(UML_SETJMP(&here) == 0) 517 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); 518 unblock_signals(); 519 520 cb_proc = NULL; 521 cb_arg = NULL; 522 cb_back = NULL; 523 } 524 525 void halt_skas(void) 526 { 527 block_signals(); 528 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); 529 } 530 531 void reboot_skas(void) 532 { 533 block_signals(); 534 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); 535 } 536 537 void switch_mm_skas(struct mm_id *mm_idp) 538 { 539 int err; 540 541 #warning need cpu pid in switch_mm_skas 542 if(proc_mm){ 543 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, 544 mm_idp->u.mm_fd); 545 if(err) 546 panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " 547 "errno = %d\n", errno); 548 } 549 else userspace_pid[0] = mm_idp->u.pid; 550 } 551