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