LCOV - code coverage report
Current view: top level - arch/um/os-Linux/skas - process.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 42 270 15.6 %
Date: 2023-03-27 20:00:47 Functions: 6 18 33.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
       4             :  * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       5             :  */
       6             : 
       7             : #include <stdlib.h>
       8             : #include <stdbool.h>
       9             : #include <unistd.h>
      10             : #include <sched.h>
      11             : #include <errno.h>
      12             : #include <string.h>
      13             : #include <sys/mman.h>
      14             : #include <sys/wait.h>
      15             : #include <asm/unistd.h>
      16             : #include <as-layout.h>
      17             : #include <init.h>
      18             : #include <kern_util.h>
      19             : #include <mem.h>
      20             : #include <os.h>
      21             : #include <ptrace_user.h>
      22             : #include <registers.h>
      23             : #include <skas.h>
      24             : #include <sysdep/stub.h>
      25             : #include <linux/threads.h>
      26             : 
      27           0 : int is_skas_winch(int pid, int fd, void *data)
      28             : {
      29           0 :         return pid == getpgrp();
      30             : }
      31             : 
      32             : static const char *ptrace_reg_name(int idx)
      33             : {
      34             : #define R(n) case HOST_##n: return #n
      35             : 
      36             :         switch (idx) {
      37             : #ifdef __x86_64__
      38             :         R(BX);
      39             :         R(CX);
      40             :         R(DI);
      41             :         R(SI);
      42             :         R(DX);
      43             :         R(BP);
      44             :         R(AX);
      45             :         R(R8);
      46             :         R(R9);
      47             :         R(R10);
      48             :         R(R11);
      49             :         R(R12);
      50             :         R(R13);
      51             :         R(R14);
      52             :         R(R15);
      53             :         R(ORIG_AX);
      54             :         R(CS);
      55             :         R(SS);
      56             :         R(EFLAGS);
      57             : #elif defined(__i386__)
      58             :         R(IP);
      59             :         R(SP);
      60             :         R(EFLAGS);
      61             :         R(AX);
      62             :         R(BX);
      63             :         R(CX);
      64             :         R(DX);
      65             :         R(SI);
      66             :         R(DI);
      67             :         R(BP);
      68             :         R(CS);
      69             :         R(SS);
      70             :         R(DS);
      71             :         R(FS);
      72             :         R(ES);
      73             :         R(GS);
      74             :         R(ORIG_AX);
      75             : #endif
      76             :         }
      77             :         return "";
      78             : }
      79             : 
      80           0 : static int ptrace_dump_regs(int pid)
      81             : {
      82             :         unsigned long regs[MAX_REG_NR];
      83             :         int i;
      84             : 
      85           0 :         if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
      86           0 :                 return -errno;
      87             : 
      88           0 :         printk(UM_KERN_ERR "Stub registers -\n");
      89           0 :         for (i = 0; i < ARRAY_SIZE(regs); i++) {
      90           0 :                 const char *regname = ptrace_reg_name(i);
      91             : 
      92           0 :                 printk(UM_KERN_ERR "\t%s\t(%2d): %lx\n", regname, i, regs[i]);
      93             :         }
      94             : 
      95             :         return 0;
      96             : }
      97             : 
      98             : /*
      99             :  * Signals that are OK to receive in the stub - we'll just continue it.
     100             :  * SIGWINCH will happen when UML is inside a detached screen.
     101             :  */
     102             : #define STUB_SIG_MASK ((1 << SIGALRM) | (1 << SIGWINCH))
     103             : 
     104             : /* Signals that the stub will finish with - anything else is an error */
     105             : #define STUB_DONE_MASK (1 << SIGTRAP)
     106             : 
     107           0 : void wait_stub_done(int pid)
     108             : {
     109             :         int n, status, err;
     110             : 
     111             :         while (1) {
     112           0 :                 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
     113           0 :                 if ((n < 0) || !WIFSTOPPED(status))
     114             :                         goto bad_wait;
     115             : 
     116           0 :                 if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
     117             :                         break;
     118             : 
     119           0 :                 err = ptrace(PTRACE_CONT, pid, 0, 0);
     120           0 :                 if (err) {
     121           0 :                         printk(UM_KERN_ERR "%s : continue failed, errno = %d\n",
     122             :                                __func__, errno);
     123           0 :                         fatal_sigsegv();
     124             :                 }
     125             :         }
     126             : 
     127           0 :         if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
     128           0 :                 return;
     129             : 
     130             : bad_wait:
     131           0 :         err = ptrace_dump_regs(pid);
     132           0 :         if (err)
     133           0 :                 printk(UM_KERN_ERR "Failed to get registers from stub, errno = %d\n",
     134             :                        -err);
     135           0 :         printk(UM_KERN_ERR "%s : failed to wait for SIGTRAP, pid = %d, n = %d, errno = %d, status = 0x%x\n",
     136             :                __func__, pid, n, errno, status);
     137           0 :         fatal_sigsegv();
     138             : }
     139             : 
     140             : extern unsigned long current_stub_stack(void);
     141             : 
     142           0 : static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
     143             : {
     144             :         int err;
     145             : 
     146           0 :         err = get_fp_registers(pid, aux_fp_regs);
     147           0 :         if (err < 0) {
     148           0 :                 printk(UM_KERN_ERR "save_fp_registers returned %d\n",
     149             :                        err);
     150           0 :                 fatal_sigsegv();
     151             :         }
     152           0 :         err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
     153           0 :         if (err) {
     154           0 :                 printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
     155             :                        "errno = %d\n", pid, errno);
     156           0 :                 fatal_sigsegv();
     157             :         }
     158           0 :         wait_stub_done(pid);
     159             : 
     160             :         /*
     161             :          * faultinfo is prepared by the stub_segv_handler at start of
     162             :          * the stub stack page. We just have to copy it.
     163             :          */
     164           0 :         memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
     165             : 
     166           0 :         err = put_fp_registers(pid, aux_fp_regs);
     167           0 :         if (err < 0) {
     168           0 :                 printk(UM_KERN_ERR "put_fp_registers returned %d\n",
     169             :                        err);
     170           0 :                 fatal_sigsegv();
     171             :         }
     172           0 : }
     173             : 
     174             : static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
     175             : {
     176             :         get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs);
     177             :         segv(regs->faultinfo, 0, 1, NULL);
     178             : }
     179             : 
     180             : /*
     181             :  * To use the same value of using_sysemu as the caller, ask it that value
     182             :  * (in local_using_sysemu
     183             :  */
     184           0 : static void handle_trap(int pid, struct uml_pt_regs *regs,
     185             :                         int local_using_sysemu)
     186             : {
     187             :         int err, status;
     188             : 
     189           0 :         if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
     190           0 :                 fatal_sigsegv();
     191             : 
     192           0 :         if (!local_using_sysemu)
     193             :         {
     194           0 :                 err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
     195             :                              __NR_getpid);
     196           0 :                 if (err < 0) {
     197           0 :                         printk(UM_KERN_ERR "%s - nullifying syscall failed, errno = %d\n",
     198             :                                __func__, errno);
     199           0 :                         fatal_sigsegv();
     200             :                 }
     201             : 
     202           0 :                 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
     203           0 :                 if (err < 0) {
     204           0 :                         printk(UM_KERN_ERR "%s - continuing to end of syscall failed, errno = %d\n",
     205             :                                __func__, errno);
     206           0 :                         fatal_sigsegv();
     207             :                 }
     208             : 
     209           0 :                 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
     210           0 :                 if ((err < 0) || !WIFSTOPPED(status) ||
     211           0 :                     (WSTOPSIG(status) != SIGTRAP + 0x80)) {
     212           0 :                         err = ptrace_dump_regs(pid);
     213           0 :                         if (err)
     214           0 :                                 printk(UM_KERN_ERR "Failed to get registers from process, errno = %d\n",
     215             :                                        -err);
     216           0 :                         printk(UM_KERN_ERR "%s - failed to wait at end of syscall, errno = %d, status = %d\n",
     217             :                                __func__, errno, status);
     218           0 :                         fatal_sigsegv();
     219             :                 }
     220             :         }
     221             : 
     222           0 :         handle_syscall(regs);
     223           0 : }
     224             : 
     225             : extern char __syscall_stub_start[];
     226             : 
     227             : /**
     228             :  * userspace_tramp() - userspace trampoline
     229             :  * @stack:      pointer to the new userspace stack page, can be NULL, if? FIXME:
     230             :  *
     231             :  * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed.
     232             :  * This function will run on a temporary stack page.
     233             :  * It ptrace()'es itself, then
     234             :  * Two pages are mapped into the userspace address space:
     235             :  * - STUB_CODE (with EXEC), which contains the skas stub code
     236             :  * - 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.
     237             :  * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process.
     238             :  * And last the process stops itself to give control to the UML kernel for this userspace process.
     239             :  *
     240             :  * Return: Always zero, otherwise the current userspace process is ended with non null exit() call
     241             :  */
     242           0 : static int userspace_tramp(void *stack)
     243             : {
     244             :         void *addr;
     245             :         int fd;
     246             :         unsigned long long offset;
     247             : 
     248           0 :         ptrace(PTRACE_TRACEME, 0, 0, 0);
     249             : 
     250           0 :         signal(SIGTERM, SIG_DFL);
     251           0 :         signal(SIGWINCH, SIG_IGN);
     252             : 
     253           0 :         fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset);
     254           0 :         addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
     255             :                       PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
     256           0 :         if (addr == MAP_FAILED) {
     257           0 :                 printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, errno = %d\n",
     258             :                        STUB_CODE, errno);
     259           0 :                 exit(1);
     260             :         }
     261             : 
     262           0 :         if (stack != NULL) {
     263           0 :                 fd = phys_mapping(uml_to_phys(stack), &offset);
     264           0 :                 addr = mmap((void *) STUB_DATA,
     265             :                             UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
     266             :                             MAP_FIXED | MAP_SHARED, fd, offset);
     267           0 :                 if (addr == MAP_FAILED) {
     268           0 :                         printk(UM_KERN_ERR "mapping segfault stack at 0x%lx failed, errno = %d\n",
     269             :                                STUB_DATA, errno);
     270           0 :                         exit(1);
     271             :                 }
     272             :         }
     273           0 :         if (stack != NULL) {
     274             :                 struct sigaction sa;
     275             : 
     276           0 :                 unsigned long v = STUB_CODE +
     277           0 :                                   (unsigned long) stub_segv_handler -
     278             :                                   (unsigned long) __syscall_stub_start;
     279             : 
     280           0 :                 set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
     281           0 :                 sigemptyset(&sa.sa_mask);
     282           0 :                 sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
     283           0 :                 sa.sa_sigaction = (void *) v;
     284           0 :                 sa.sa_restorer = NULL;
     285           0 :                 if (sigaction(SIGSEGV, &sa, NULL) < 0) {
     286           0 :                         printk(UM_KERN_ERR "%s - setting SIGSEGV handler failed - errno = %d\n",
     287             :                                __func__, errno);
     288           0 :                         exit(1);
     289             :                 }
     290             :         }
     291             : 
     292           0 :         kill(os_getpid(), SIGSTOP);
     293           0 :         return 0;
     294             : }
     295             : 
     296             : int userspace_pid[NR_CPUS];
     297             : int kill_userspace_mm[NR_CPUS];
     298             : 
     299             : /**
     300             :  * start_userspace() - prepare a new userspace process
     301             :  * @stub_stack: pointer to the stub stack. Can be NULL, if? FIXME:
     302             :  *
     303             :  * Setups a new temporary stack page that is used while userspace_tramp() runs
     304             :  * Clones the kernel process into a new userspace process, with FDs only.
     305             :  *
     306             :  * Return: When positive: the process id of the new userspace process,
     307             :  *         when negative: an error number.
     308             :  * FIXME: can PIDs become negative?!
     309             :  */
     310           0 : int start_userspace(unsigned long stub_stack)
     311             : {
     312             :         void *stack;
     313             :         unsigned long sp;
     314             :         int pid, status, n, flags, err;
     315             : 
     316             :         /* setup a temporary stack page */
     317           0 :         stack = mmap(NULL, UM_KERN_PAGE_SIZE,
     318             :                      PROT_READ | PROT_WRITE | PROT_EXEC,
     319             :                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     320           0 :         if (stack == MAP_FAILED) {
     321           0 :                 err = -errno;
     322           0 :                 printk(UM_KERN_ERR "%s : mmap failed, errno = %d\n",
     323             :                        __func__, errno);
     324           0 :                 return err;
     325             :         }
     326             : 
     327             :         /* set stack pointer to the end of the stack page, so it can grow downwards */
     328           0 :         sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;
     329             : 
     330           0 :         flags = CLONE_FILES | SIGCHLD;
     331             : 
     332             :         /* clone into new userspace process */
     333           0 :         pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
     334           0 :         if (pid < 0) {
     335           0 :                 err = -errno;
     336           0 :                 printk(UM_KERN_ERR "%s : clone failed, errno = %d\n",
     337             :                        __func__, errno);
     338           0 :                 return err;
     339             :         }
     340             : 
     341             :         do {
     342           0 :                 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
     343           0 :                 if (n < 0) {
     344           0 :                         err = -errno;
     345           0 :                         printk(UM_KERN_ERR "%s : wait failed, errno = %d\n",
     346             :                                __func__, errno);
     347           0 :                         goto out_kill;
     348             :                 }
     349           0 :         } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));
     350             : 
     351           0 :         if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
     352           0 :                 err = -EINVAL;
     353           0 :                 printk(UM_KERN_ERR "%s : expected SIGSTOP, got status = %d\n",
     354             :                        __func__, status);
     355           0 :                 goto out_kill;
     356             :         }
     357             : 
     358           0 :         if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
     359             :                    (void *) PTRACE_O_TRACESYSGOOD) < 0) {
     360           0 :                 err = -errno;
     361           0 :                 printk(UM_KERN_ERR "%s : PTRACE_OLDSETOPTIONS failed, errno = %d\n",
     362             :                        __func__, errno);
     363           0 :                 goto out_kill;
     364             :         }
     365             : 
     366           0 :         if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
     367           0 :                 err = -errno;
     368           0 :                 printk(UM_KERN_ERR "%s : munmap failed, errno = %d\n",
     369             :                        __func__, errno);
     370           0 :                 goto out_kill;
     371             :         }
     372             : 
     373             :         return pid;
     374             : 
     375             :  out_kill:
     376           0 :         os_kill_ptraced_process(pid, 1);
     377           0 :         return err;
     378             : }
     379             : 
     380           0 : void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
     381             : {
     382           0 :         int err, status, op, pid = userspace_pid[0];
     383             :         /* To prevent races if using_sysemu changes under us.*/
     384             :         int local_using_sysemu;
     385             :         siginfo_t si;
     386             : 
     387             :         /* Handle any immediate reschedules or signals */
     388           0 :         interrupt_end();
     389             : 
     390             :         while (1) {
     391           0 :                 if (kill_userspace_mm[0])
     392           0 :                         fatal_sigsegv();
     393             : 
     394             :                 /*
     395             :                  * This can legitimately fail if the process loads a
     396             :                  * bogus value into a segment register.  It will
     397             :                  * segfault and PTRACE_GETREGS will read that value
     398             :                  * out of the process.  However, PTRACE_SETREGS will
     399             :                  * fail.  In this case, there is nothing to do but
     400             :                  * just kill the process.
     401             :                  */
     402           0 :                 if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) {
     403           0 :                         printk(UM_KERN_ERR "%s - ptrace set regs failed, errno = %d\n",
     404             :                                __func__, errno);
     405           0 :                         fatal_sigsegv();
     406             :                 }
     407             : 
     408           0 :                 if (put_fp_registers(pid, regs->fp)) {
     409           0 :                         printk(UM_KERN_ERR "%s - ptrace set fp regs failed, errno = %d\n",
     410             :                                __func__, errno);
     411           0 :                         fatal_sigsegv();
     412             :                 }
     413             : 
     414             :                 /* Now we set local_using_sysemu to be used for one loop */
     415           0 :                 local_using_sysemu = get_using_sysemu();
     416             : 
     417           0 :                 op = SELECT_PTRACE_OPERATION(local_using_sysemu,
     418             :                                              singlestepping(NULL));
     419             : 
     420           0 :                 if (ptrace(op, pid, 0, 0)) {
     421           0 :                         printk(UM_KERN_ERR "%s - ptrace continue failed, op = %d, errno = %d\n",
     422             :                                __func__, op, errno);
     423           0 :                         fatal_sigsegv();
     424             :                 }
     425             : 
     426           0 :                 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
     427           0 :                 if (err < 0) {
     428           0 :                         printk(UM_KERN_ERR "%s - wait failed, errno = %d\n",
     429             :                                __func__, errno);
     430           0 :                         fatal_sigsegv();
     431             :                 }
     432             : 
     433           0 :                 regs->is_user = 1;
     434           0 :                 if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
     435           0 :                         printk(UM_KERN_ERR "%s - PTRACE_GETREGS failed, errno = %d\n",
     436             :                                __func__, errno);
     437           0 :                         fatal_sigsegv();
     438             :                 }
     439             : 
     440           0 :                 if (get_fp_registers(pid, regs->fp)) {
     441           0 :                         printk(UM_KERN_ERR "%s -  get_fp_registers failed, errno = %d\n",
     442             :                                __func__, errno);
     443           0 :                         fatal_sigsegv();
     444             :                 }
     445             : 
     446           0 :                 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
     447             : 
     448           0 :                 if (WIFSTOPPED(status)) {
     449           0 :                         int sig = WSTOPSIG(status);
     450             : 
     451             :                         /* These signal handlers need the si argument.
     452             :                          * The SIGIO and SIGALARM handlers which constitute the
     453             :                          * majority of invocations, do not use it.
     454             :                          */
     455             :                         switch (sig) {
     456             :                         case SIGSEGV:
     457             :                         case SIGTRAP:
     458             :                         case SIGILL:
     459             :                         case SIGBUS:
     460             :                         case SIGFPE:
     461             :                         case SIGWINCH:
     462           0 :                                 ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
     463           0 :                                 break;
     464             :                         }
     465             : 
     466           0 :                         switch (sig) {
     467             :                         case SIGSEGV:
     468             :                                 if (PTRACE_FULL_FAULTINFO) {
     469           0 :                                         get_skas_faultinfo(pid,
     470             :                                                            &regs->faultinfo, aux_fp_regs);
     471           0 :                                         (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
     472             :                                                              regs);
     473             :                                 }
     474             :                                 else handle_segv(pid, regs, aux_fp_regs);
     475           0 :                                 break;
     476             :                         case SIGTRAP + 0x80:
     477           0 :                                 handle_trap(pid, regs, local_using_sysemu);
     478           0 :                                 break;
     479             :                         case SIGTRAP:
     480           0 :                                 relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
     481           0 :                                 break;
     482             :                         case SIGALRM:
     483             :                                 break;
     484             :                         case SIGIO:
     485             :                         case SIGILL:
     486             :                         case SIGBUS:
     487             :                         case SIGFPE:
     488             :                         case SIGWINCH:
     489           0 :                                 block_signals_trace();
     490           0 :                                 (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
     491           0 :                                 unblock_signals_trace();
     492           0 :                                 break;
     493             :                         default:
     494           0 :                                 printk(UM_KERN_ERR "%s - child stopped with signal %d\n",
     495             :                                        __func__, sig);
     496           0 :                                 fatal_sigsegv();
     497             :                         }
     498           0 :                         pid = userspace_pid[0];
     499           0 :                         interrupt_end();
     500             : 
     501             :                         /* Avoid -ERESTARTSYS handling in host */
     502             :                         if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
     503           0 :                                 PT_SYSCALL_NR(regs->gp) = -1;
     504             :                 }
     505             :         }
     506             : }
     507             : 
     508             : static unsigned long thread_regs[MAX_REG_NR];
     509             : static unsigned long thread_fp_regs[FP_SIZE];
     510             : 
     511           1 : static int __init init_thread_regs(void)
     512             : {
     513           1 :         get_safe_registers(thread_regs, thread_fp_regs);
     514             :         /* Set parent's instruction pointer to start of clone-stub */
     515           1 :         thread_regs[REGS_IP_INDEX] = STUB_CODE +
     516           1 :                                 (unsigned long) stub_clone_handler -
     517             :                                 (unsigned long) __syscall_stub_start;
     518           1 :         thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
     519             :                 sizeof(void *);
     520             : #ifdef __SIGNAL_FRAMESIZE
     521             :         thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
     522             : #endif
     523           1 :         return 0;
     524             : }
     525             : 
     526             : __initcall(init_thread_regs);
     527             : 
     528           0 : int copy_context_skas0(unsigned long new_stack, int pid)
     529             : {
     530             :         int err;
     531           0 :         unsigned long current_stack = current_stub_stack();
     532           0 :         struct stub_data *data = (struct stub_data *) current_stack;
     533           0 :         struct stub_data *child_data = (struct stub_data *) new_stack;
     534             :         unsigned long long new_offset;
     535           0 :         int new_fd = phys_mapping(uml_to_phys((void *)new_stack), &new_offset);
     536             : 
     537             :         /*
     538             :          * prepare offset and fd of child's stack as argument for parent's
     539             :          * and child's mmap2 calls
     540             :          */
     541           0 :         *data = ((struct stub_data) {
     542             :                 .offset = MMAP_OFFSET(new_offset),
     543             :                 .fd     = new_fd,
     544             :                 .parent_err = -ESRCH,
     545             :                 .child_err = 0,
     546             :         });
     547             : 
     548           0 :         *child_data = ((struct stub_data) {
     549             :                 .child_err = -ESRCH,
     550             :         });
     551             : 
     552           0 :         err = ptrace_setregs(pid, thread_regs);
     553           0 :         if (err < 0) {
     554           0 :                 err = -errno;
     555           0 :                 printk(UM_KERN_ERR "%s : PTRACE_SETREGS failed, pid = %d, errno = %d\n",
     556             :                       __func__, pid, -err);
     557           0 :                 return err;
     558             :         }
     559             : 
     560           0 :         err = put_fp_registers(pid, thread_fp_regs);
     561           0 :         if (err < 0) {
     562           0 :                 printk(UM_KERN_ERR "%s : put_fp_registers failed, pid = %d, err = %d\n",
     563             :                        __func__, pid, err);
     564           0 :                 return err;
     565             :         }
     566             : 
     567             :         /*
     568             :          * Wait, until parent has finished its work: read child's pid from
     569             :          * parent's stack, and check, if bad result.
     570             :          */
     571           0 :         err = ptrace(PTRACE_CONT, pid, 0, 0);
     572           0 :         if (err) {
     573           0 :                 err = -errno;
     574           0 :                 printk(UM_KERN_ERR "Failed to continue new process, pid = %d, errno = %d\n",
     575             :                        pid, errno);
     576           0 :                 return err;
     577             :         }
     578             : 
     579           0 :         wait_stub_done(pid);
     580             : 
     581           0 :         pid = data->parent_err;
     582           0 :         if (pid < 0) {
     583           0 :                 printk(UM_KERN_ERR "%s - stub-parent reports error %d\n",
     584             :                       __func__, -pid);
     585           0 :                 return pid;
     586             :         }
     587             : 
     588             :         /*
     589             :          * Wait, until child has finished too: read child's result from
     590             :          * child's stack and check it.
     591             :          */
     592           0 :         wait_stub_done(pid);
     593           0 :         if (child_data->child_err != STUB_DATA) {
     594           0 :                 printk(UM_KERN_ERR "%s - stub-child %d reports error %ld\n",
     595             :                        __func__, pid, data->child_err);
     596           0 :                 err = data->child_err;
     597           0 :                 goto out_kill;
     598             :         }
     599             : 
     600           0 :         if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
     601             :                    (void *)PTRACE_O_TRACESYSGOOD) < 0) {
     602           0 :                 err = -errno;
     603           0 :                 printk(UM_KERN_ERR "%s : PTRACE_OLDSETOPTIONS failed, errno = %d\n",
     604             :                        __func__, errno);
     605           0 :                 goto out_kill;
     606             :         }
     607             : 
     608             :         return pid;
     609             : 
     610             :  out_kill:
     611           0 :         os_kill_ptraced_process(pid, 1);
     612           0 :         return err;
     613             : }
     614             : 
     615         340 : void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
     616             : {
     617         340 :         (*buf)[0].JB_IP = (unsigned long) handler;
     618         340 :         (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
     619             :                 sizeof(void *);
     620         340 : }
     621             : 
     622             : #define INIT_JMP_NEW_THREAD 0
     623             : #define INIT_JMP_CALLBACK 1
     624             : #define INIT_JMP_HALT 2
     625             : #define INIT_JMP_REBOOT 3
     626             : 
     627        2210 : void switch_threads(jmp_buf *me, jmp_buf *you)
     628             : {
     629        2210 :         if (UML_SETJMP(me) == 0)
     630        2210 :                 UML_LONGJMP(you, 1);
     631        1870 : }
     632             : 
     633             : static jmp_buf initial_jmpbuf;
     634             : 
     635             : /* XXX Make these percpu */
     636             : static void (*cb_proc)(void *arg);
     637             : static void *cb_arg;
     638             : static jmp_buf *cb_back;
     639             : 
     640           1 : int start_idle_thread(void *stack, jmp_buf *switch_buf)
     641             : {
     642             :         int n;
     643             : 
     644           1 :         set_handler(SIGWINCH);
     645             : 
     646             :         /*
     647             :          * Can't use UML_SETJMP or UML_LONGJMP here because they save
     648             :          * and restore signals, with the possible side-effect of
     649             :          * trying to handle any signals which came when they were
     650             :          * blocked, which can't be done on this stack.
     651             :          * Signals must be blocked when jumping back here and restored
     652             :          * after returning to the jumper.
     653             :          */
     654           1 :         n = setjmp(initial_jmpbuf);
     655           3 :         switch (n) {
     656             :         case INIT_JMP_NEW_THREAD:
     657           1 :                 (*switch_buf)[0].JB_IP = (unsigned long) uml_finishsetup;
     658           2 :                 (*switch_buf)[0].JB_SP = (unsigned long) stack +
     659           1 :                         UM_THREAD_SIZE - sizeof(void *);
     660           1 :                 break;
     661             :         case INIT_JMP_CALLBACK:
     662           1 :                 (*cb_proc)(cb_arg);
     663           1 :                 longjmp(*cb_back, 1);
     664           0 :                 break;
     665             :         case INIT_JMP_HALT:
     666           1 :                 kmalloc_ok = 0;
     667           1 :                 return 0;
     668             :         case INIT_JMP_REBOOT:
     669           0 :                 kmalloc_ok = 0;
     670           0 :                 return 1;
     671             :         default:
     672           0 :                 printk(UM_KERN_ERR "Bad sigsetjmp return in %s - %d\n",
     673             :                        __func__, n);
     674           0 :                 fatal_sigsegv();
     675             :         }
     676           1 :         longjmp(*switch_buf, 1);
     677             : 
     678             :         /* unreachable */
     679           0 :         printk(UM_KERN_ERR "impossible long jump!");
     680           0 :         fatal_sigsegv();
     681             :         return 0;
     682             : }
     683             : 
     684           1 : void initial_thread_cb_skas(void (*proc)(void *), void *arg)
     685             : {
     686             :         jmp_buf here;
     687             : 
     688           1 :         cb_proc = proc;
     689           1 :         cb_arg = arg;
     690           1 :         cb_back = &here;
     691             : 
     692           1 :         block_signals_trace();
     693           1 :         if (UML_SETJMP(&here) == 0)
     694           1 :                 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
     695           1 :         unblock_signals_trace();
     696             : 
     697           1 :         cb_proc = NULL;
     698           1 :         cb_arg = NULL;
     699           1 :         cb_back = NULL;
     700           1 : }
     701             : 
     702           1 : void halt_skas(void)
     703             : {
     704           1 :         block_signals_trace();
     705           1 :         UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
     706           0 : }
     707             : 
     708             : static bool noreboot;
     709             : 
     710           0 : static int __init noreboot_cmd_param(char *str, int *add)
     711             : {
     712           0 :         noreboot = true;
     713           0 :         return 0;
     714             : }
     715             : 
     716             : __uml_setup("noreboot", noreboot_cmd_param,
     717             : "noreboot\n"
     718             : "    Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n"
     719             : "    This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n"
     720             : "    crashes in CI\n");
     721             : 
     722           0 : void reboot_skas(void)
     723             : {
     724           0 :         block_signals_trace();
     725           0 :         UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT);
     726           0 : }
     727             : 
     728           0 : void __switch_mm(struct mm_id *mm_idp)
     729             : {
     730           0 :         userspace_pid[0] = mm_idp->u.pid;
     731           0 :         kill_userspace_mm[0] = mm_idp->kill;
     732           0 : }

Generated by: LCOV version 1.14