0001
0002
0003
0004
0005
0006
0007 #include <stdlib.h>
0008 #include <stdbool.h>
0009 #include <unistd.h>
0010 #include <sched.h>
0011 #include <errno.h>
0012 #include <string.h>
0013 #include <sys/mman.h>
0014 #include <sys/wait.h>
0015 #include <asm/unistd.h>
0016 #include <as-layout.h>
0017 #include <init.h>
0018 #include <kern_util.h>
0019 #include <mem.h>
0020 #include <os.h>
0021 #include <ptrace_user.h>
0022 #include <registers.h>
0023 #include <skas.h>
0024 #include <sysdep/stub.h>
0025 #include <linux/threads.h>
0026
0027 int is_skas_winch(int pid, int fd, void *data)
0028 {
0029 return pid == getpgrp();
0030 }
0031
0032 static const char *ptrace_reg_name(int idx)
0033 {
0034 #define R(n) case HOST_##n: return #n
0035
0036 switch (idx) {
0037 #ifdef __x86_64__
0038 R(BX);
0039 R(CX);
0040 R(DI);
0041 R(SI);
0042 R(DX);
0043 R(BP);
0044 R(AX);
0045 R(R8);
0046 R(R9);
0047 R(R10);
0048 R(R11);
0049 R(R12);
0050 R(R13);
0051 R(R14);
0052 R(R15);
0053 R(ORIG_AX);
0054 R(CS);
0055 R(SS);
0056 R(EFLAGS);
0057 #elif defined(__i386__)
0058 R(IP);
0059 R(SP);
0060 R(EFLAGS);
0061 R(AX);
0062 R(BX);
0063 R(CX);
0064 R(DX);
0065 R(SI);
0066 R(DI);
0067 R(BP);
0068 R(CS);
0069 R(SS);
0070 R(DS);
0071 R(FS);
0072 R(ES);
0073 R(GS);
0074 R(ORIG_AX);
0075 #endif
0076 }
0077 return "";
0078 }
0079
0080 static int ptrace_dump_regs(int pid)
0081 {
0082 unsigned long regs[MAX_REG_NR];
0083 int i;
0084
0085 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
0086 return -errno;
0087
0088 printk(UM_KERN_ERR "Stub registers -\n");
0089 for (i = 0; i < ARRAY_SIZE(regs); i++) {
0090 const char *regname = ptrace_reg_name(i);
0091
0092 printk(UM_KERN_ERR "\t%s\t(%2d): %lx\n", regname, i, regs[i]);
0093 }
0094
0095 return 0;
0096 }
0097
0098
0099
0100
0101
0102 #define STUB_SIG_MASK ((1 << SIGALRM) | (1 << SIGWINCH))
0103
0104
0105 #define STUB_DONE_MASK (1 << SIGTRAP)
0106
0107 void wait_stub_done(int pid)
0108 {
0109 int n, status, err;
0110
0111 while (1) {
0112 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
0113 if ((n < 0) || !WIFSTOPPED(status))
0114 goto bad_wait;
0115
0116 if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
0117 break;
0118
0119 err = ptrace(PTRACE_CONT, pid, 0, 0);
0120 if (err) {
0121 printk(UM_KERN_ERR "wait_stub_done : continue failed, "
0122 "errno = %d\n", errno);
0123 fatal_sigsegv();
0124 }
0125 }
0126
0127 if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
0128 return;
0129
0130 bad_wait:
0131 err = ptrace_dump_regs(pid);
0132 if (err)
0133 printk(UM_KERN_ERR "Failed to get registers from stub, "
0134 "errno = %d\n", -err);
0135 printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
0136 "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
0137 status);
0138 fatal_sigsegv();
0139 }
0140
0141 extern unsigned long current_stub_stack(void);
0142
0143 static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
0144 {
0145 int err;
0146
0147 err = get_fp_registers(pid, aux_fp_regs);
0148 if (err < 0) {
0149 printk(UM_KERN_ERR "save_fp_registers returned %d\n",
0150 err);
0151 fatal_sigsegv();
0152 }
0153 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
0154 if (err) {
0155 printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
0156 "errno = %d\n", pid, errno);
0157 fatal_sigsegv();
0158 }
0159 wait_stub_done(pid);
0160
0161
0162
0163
0164
0165 memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
0166
0167 err = put_fp_registers(pid, aux_fp_regs);
0168 if (err < 0) {
0169 printk(UM_KERN_ERR "put_fp_registers returned %d\n",
0170 err);
0171 fatal_sigsegv();
0172 }
0173 }
0174
0175 static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
0176 {
0177 get_skas_faultinfo(pid, ®s->faultinfo, aux_fp_regs);
0178 segv(regs->faultinfo, 0, 1, NULL);
0179 }
0180
0181
0182
0183
0184
0185 static void handle_trap(int pid, struct uml_pt_regs *regs,
0186 int local_using_sysemu)
0187 {
0188 int err, status;
0189
0190 if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
0191 fatal_sigsegv();
0192
0193 if (!local_using_sysemu)
0194 {
0195 err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
0196 __NR_getpid);
0197 if (err < 0) {
0198 printk(UM_KERN_ERR "handle_trap - nullifying syscall "
0199 "failed, errno = %d\n", errno);
0200 fatal_sigsegv();
0201 }
0202
0203 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
0204 if (err < 0) {
0205 printk(UM_KERN_ERR "handle_trap - continuing to end of "
0206 "syscall failed, errno = %d\n", errno);
0207 fatal_sigsegv();
0208 }
0209
0210 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
0211 if ((err < 0) || !WIFSTOPPED(status) ||
0212 (WSTOPSIG(status) != SIGTRAP + 0x80)) {
0213 err = ptrace_dump_regs(pid);
0214 if (err)
0215 printk(UM_KERN_ERR "Failed to get registers "
0216 "from process, errno = %d\n", -err);
0217 printk(UM_KERN_ERR "handle_trap - failed to wait at "
0218 "end of syscall, errno = %d, status = %d\n",
0219 errno, status);
0220 fatal_sigsegv();
0221 }
0222 }
0223
0224 handle_syscall(regs);
0225 }
0226
0227 extern char __syscall_stub_start[];
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 static int userspace_tramp(void *stack)
0245 {
0246 void *addr;
0247 int fd;
0248 unsigned long long offset;
0249
0250 ptrace(PTRACE_TRACEME, 0, 0, 0);
0251
0252 signal(SIGTERM, SIG_DFL);
0253 signal(SIGWINCH, SIG_IGN);
0254
0255 fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset);
0256 addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
0257 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
0258 if (addr == MAP_FAILED) {
0259 printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
0260 "errno = %d\n", STUB_CODE, errno);
0261 exit(1);
0262 }
0263
0264 if (stack != NULL) {
0265 fd = phys_mapping(uml_to_phys(stack), &offset);
0266 addr = mmap((void *) STUB_DATA,
0267 UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
0268 MAP_FIXED | MAP_SHARED, fd, offset);
0269 if (addr == MAP_FAILED) {
0270 printk(UM_KERN_ERR "mapping segfault stack "
0271 "at 0x%lx failed, errno = %d\n",
0272 STUB_DATA, errno);
0273 exit(1);
0274 }
0275 }
0276 if (stack != NULL) {
0277 struct sigaction sa;
0278
0279 unsigned long v = STUB_CODE +
0280 (unsigned long) stub_segv_handler -
0281 (unsigned long) __syscall_stub_start;
0282
0283 set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
0284 sigemptyset(&sa.sa_mask);
0285 sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
0286 sa.sa_sigaction = (void *) v;
0287 sa.sa_restorer = NULL;
0288 if (sigaction(SIGSEGV, &sa, NULL) < 0) {
0289 printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
0290 "handler failed - errno = %d\n", errno);
0291 exit(1);
0292 }
0293 }
0294
0295 kill(os_getpid(), SIGSTOP);
0296 return 0;
0297 }
0298
0299 int userspace_pid[NR_CPUS];
0300 int kill_userspace_mm[NR_CPUS];
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 int start_userspace(unsigned long stub_stack)
0314 {
0315 void *stack;
0316 unsigned long sp;
0317 int pid, status, n, flags, err;
0318
0319
0320 stack = mmap(NULL, UM_KERN_PAGE_SIZE,
0321 PROT_READ | PROT_WRITE | PROT_EXEC,
0322 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0323 if (stack == MAP_FAILED) {
0324 err = -errno;
0325 printk(UM_KERN_ERR "start_userspace : mmap failed, "
0326 "errno = %d\n", errno);
0327 return err;
0328 }
0329
0330
0331 sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;
0332
0333 flags = CLONE_FILES | SIGCHLD;
0334
0335
0336 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
0337 if (pid < 0) {
0338 err = -errno;
0339 printk(UM_KERN_ERR "start_userspace : clone failed, "
0340 "errno = %d\n", errno);
0341 return err;
0342 }
0343
0344 do {
0345 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
0346 if (n < 0) {
0347 err = -errno;
0348 printk(UM_KERN_ERR "start_userspace : wait failed, "
0349 "errno = %d\n", errno);
0350 goto out_kill;
0351 }
0352 } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));
0353
0354 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
0355 err = -EINVAL;
0356 printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
0357 "status = %d\n", status);
0358 goto out_kill;
0359 }
0360
0361 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
0362 (void *) PTRACE_O_TRACESYSGOOD) < 0) {
0363 err = -errno;
0364 printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
0365 "failed, errno = %d\n", errno);
0366 goto out_kill;
0367 }
0368
0369 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
0370 err = -errno;
0371 printk(UM_KERN_ERR "start_userspace : munmap failed, "
0372 "errno = %d\n", errno);
0373 goto out_kill;
0374 }
0375
0376 return pid;
0377
0378 out_kill:
0379 os_kill_ptraced_process(pid, 1);
0380 return err;
0381 }
0382
0383 void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
0384 {
0385 int err, status, op, pid = userspace_pid[0];
0386
0387 int local_using_sysemu;
0388 siginfo_t si;
0389
0390
0391 interrupt_end();
0392
0393 while (1) {
0394 if (kill_userspace_mm[0])
0395 fatal_sigsegv();
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) {
0406 printk(UM_KERN_ERR "userspace - ptrace set regs "
0407 "failed, errno = %d\n", errno);
0408 fatal_sigsegv();
0409 }
0410
0411 if (put_fp_registers(pid, regs->fp)) {
0412 printk(UM_KERN_ERR "userspace - ptrace set fp regs "
0413 "failed, errno = %d\n", errno);
0414 fatal_sigsegv();
0415 }
0416
0417
0418 local_using_sysemu = get_using_sysemu();
0419
0420 op = SELECT_PTRACE_OPERATION(local_using_sysemu,
0421 singlestepping(NULL));
0422
0423 if (ptrace(op, pid, 0, 0)) {
0424 printk(UM_KERN_ERR "userspace - ptrace continue "
0425 "failed, op = %d, errno = %d\n", op, errno);
0426 fatal_sigsegv();
0427 }
0428
0429 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
0430 if (err < 0) {
0431 printk(UM_KERN_ERR "userspace - wait failed, "
0432 "errno = %d\n", errno);
0433 fatal_sigsegv();
0434 }
0435
0436 regs->is_user = 1;
0437 if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
0438 printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
0439 "errno = %d\n", errno);
0440 fatal_sigsegv();
0441 }
0442
0443 if (get_fp_registers(pid, regs->fp)) {
0444 printk(UM_KERN_ERR "userspace - get_fp_registers failed, "
0445 "errno = %d\n", errno);
0446 fatal_sigsegv();
0447 }
0448
0449 UPT_SYSCALL_NR(regs) = -1;
0450
0451 if (WIFSTOPPED(status)) {
0452 int sig = WSTOPSIG(status);
0453
0454
0455
0456
0457
0458 switch (sig) {
0459 case SIGSEGV:
0460 case SIGTRAP:
0461 case SIGILL:
0462 case SIGBUS:
0463 case SIGFPE:
0464 case SIGWINCH:
0465 ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
0466 break;
0467 }
0468
0469 switch (sig) {
0470 case SIGSEGV:
0471 if (PTRACE_FULL_FAULTINFO) {
0472 get_skas_faultinfo(pid,
0473 ®s->faultinfo, aux_fp_regs);
0474 (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
0475 regs);
0476 }
0477 else handle_segv(pid, regs, aux_fp_regs);
0478 break;
0479 case SIGTRAP + 0x80:
0480 handle_trap(pid, regs, local_using_sysemu);
0481 break;
0482 case SIGTRAP:
0483 relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
0484 break;
0485 case SIGALRM:
0486 break;
0487 case SIGIO:
0488 case SIGILL:
0489 case SIGBUS:
0490 case SIGFPE:
0491 case SIGWINCH:
0492 block_signals_trace();
0493 (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
0494 unblock_signals_trace();
0495 break;
0496 default:
0497 printk(UM_KERN_ERR "userspace - child stopped "
0498 "with signal %d\n", sig);
0499 fatal_sigsegv();
0500 }
0501 pid = userspace_pid[0];
0502 interrupt_end();
0503
0504
0505 if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
0506 PT_SYSCALL_NR(regs->gp) = -1;
0507 }
0508 }
0509 }
0510
0511 static unsigned long thread_regs[MAX_REG_NR];
0512 static unsigned long thread_fp_regs[FP_SIZE];
0513
0514 static int __init init_thread_regs(void)
0515 {
0516 get_safe_registers(thread_regs, thread_fp_regs);
0517
0518 thread_regs[REGS_IP_INDEX] = STUB_CODE +
0519 (unsigned long) stub_clone_handler -
0520 (unsigned long) __syscall_stub_start;
0521 thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
0522 sizeof(void *);
0523 #ifdef __SIGNAL_FRAMESIZE
0524 thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
0525 #endif
0526 return 0;
0527 }
0528
0529 __initcall(init_thread_regs);
0530
0531 int copy_context_skas0(unsigned long new_stack, int pid)
0532 {
0533 int err;
0534 unsigned long current_stack = current_stub_stack();
0535 struct stub_data *data = (struct stub_data *) current_stack;
0536 struct stub_data *child_data = (struct stub_data *) new_stack;
0537 unsigned long long new_offset;
0538 int new_fd = phys_mapping(uml_to_phys((void *)new_stack), &new_offset);
0539
0540
0541
0542
0543
0544 *data = ((struct stub_data) {
0545 .offset = MMAP_OFFSET(new_offset),
0546 .fd = new_fd,
0547 .parent_err = -ESRCH,
0548 .child_err = 0,
0549 });
0550
0551 *child_data = ((struct stub_data) {
0552 .child_err = -ESRCH,
0553 });
0554
0555 err = ptrace_setregs(pid, thread_regs);
0556 if (err < 0) {
0557 err = -errno;
0558 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
0559 "failed, pid = %d, errno = %d\n", pid, -err);
0560 return err;
0561 }
0562
0563 err = put_fp_registers(pid, thread_fp_regs);
0564 if (err < 0) {
0565 printk(UM_KERN_ERR "copy_context_skas0 : put_fp_registers "
0566 "failed, pid = %d, err = %d\n", pid, err);
0567 return err;
0568 }
0569
0570
0571
0572
0573
0574 err = ptrace(PTRACE_CONT, pid, 0, 0);
0575 if (err) {
0576 err = -errno;
0577 printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
0578 "errno = %d\n", pid, errno);
0579 return err;
0580 }
0581
0582 wait_stub_done(pid);
0583
0584 pid = data->parent_err;
0585 if (pid < 0) {
0586 printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
0587 "error %d\n", -pid);
0588 return pid;
0589 }
0590
0591
0592
0593
0594
0595 wait_stub_done(pid);
0596 if (child_data->child_err != STUB_DATA) {
0597 printk(UM_KERN_ERR "copy_context_skas0 - stub-child %d reports "
0598 "error %ld\n", pid, data->child_err);
0599 err = data->child_err;
0600 goto out_kill;
0601 }
0602
0603 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
0604 (void *)PTRACE_O_TRACESYSGOOD) < 0) {
0605 err = -errno;
0606 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
0607 "failed, errno = %d\n", errno);
0608 goto out_kill;
0609 }
0610
0611 return pid;
0612
0613 out_kill:
0614 os_kill_ptraced_process(pid, 1);
0615 return err;
0616 }
0617
0618 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
0619 {
0620 (*buf)[0].JB_IP = (unsigned long) handler;
0621 (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
0622 sizeof(void *);
0623 }
0624
0625 #define INIT_JMP_NEW_THREAD 0
0626 #define INIT_JMP_CALLBACK 1
0627 #define INIT_JMP_HALT 2
0628 #define INIT_JMP_REBOOT 3
0629
0630 void switch_threads(jmp_buf *me, jmp_buf *you)
0631 {
0632 if (UML_SETJMP(me) == 0)
0633 UML_LONGJMP(you, 1);
0634 }
0635
0636 static jmp_buf initial_jmpbuf;
0637
0638
0639 static void (*cb_proc)(void *arg);
0640 static void *cb_arg;
0641 static jmp_buf *cb_back;
0642
0643 int start_idle_thread(void *stack, jmp_buf *switch_buf)
0644 {
0645 int n;
0646
0647 set_handler(SIGWINCH);
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657 n = setjmp(initial_jmpbuf);
0658 switch (n) {
0659 case INIT_JMP_NEW_THREAD:
0660 (*switch_buf)[0].JB_IP = (unsigned long) uml_finishsetup;
0661 (*switch_buf)[0].JB_SP = (unsigned long) stack +
0662 UM_THREAD_SIZE - sizeof(void *);
0663 break;
0664 case INIT_JMP_CALLBACK:
0665 (*cb_proc)(cb_arg);
0666 longjmp(*cb_back, 1);
0667 break;
0668 case INIT_JMP_HALT:
0669 kmalloc_ok = 0;
0670 return 0;
0671 case INIT_JMP_REBOOT:
0672 kmalloc_ok = 0;
0673 return 1;
0674 default:
0675 printk(UM_KERN_ERR "Bad sigsetjmp return in "
0676 "start_idle_thread - %d\n", n);
0677 fatal_sigsegv();
0678 }
0679 longjmp(*switch_buf, 1);
0680
0681
0682 printk(UM_KERN_ERR "impossible long jump!");
0683 fatal_sigsegv();
0684 return 0;
0685 }
0686
0687 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
0688 {
0689 jmp_buf here;
0690
0691 cb_proc = proc;
0692 cb_arg = arg;
0693 cb_back = &here;
0694
0695 block_signals_trace();
0696 if (UML_SETJMP(&here) == 0)
0697 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
0698 unblock_signals_trace();
0699
0700 cb_proc = NULL;
0701 cb_arg = NULL;
0702 cb_back = NULL;
0703 }
0704
0705 void halt_skas(void)
0706 {
0707 block_signals_trace();
0708 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
0709 }
0710
0711 static bool noreboot;
0712
0713 static int __init noreboot_cmd_param(char *str, int *add)
0714 {
0715 noreboot = true;
0716 return 0;
0717 }
0718
0719 __uml_setup("noreboot", noreboot_cmd_param,
0720 "noreboot\n"
0721 " Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n"
0722 " This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n"
0723 " crashes in CI\n");
0724
0725 void reboot_skas(void)
0726 {
0727 block_signals_trace();
0728 UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT);
0729 }
0730
0731 void __switch_mm(struct mm_id *mm_idp)
0732 {
0733 userspace_pid[0] = mm_idp->u.pid;
0734 kill_userspace_mm[0] = mm_idp->kill;
0735 }