^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) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <unistd.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 <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sys/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <os.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <mem_user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <ptrace_user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <registers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <skas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void ptrace_child(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Calling os_getpid because some libcs cached getpid incorrectly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int pid = os_getpid(), ppid = getppid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int sc_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (change_sig(SIGWINCH, 0) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) perror("ptrace");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) kill(pid, SIGKILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) kill(pid, SIGSTOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * This syscall will be intercepted by the parent. Don't call more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * once, please.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) sc_result = os_getpid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (sc_result == pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Nothing modified by the parent, we are running normally. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) else if (sc_result == ppid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Expected in check_ptrace and check_sysemu when they succeed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * in modifying the stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Serious trouble! This could be caused by a bug in host 2.6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * SKAS3/2.6 patch before release -V6, together with a bug in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * the UML code itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ret = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) exit(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void fatal_perror(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) perror(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void fatal(char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) va_start(list, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) vfprintf(stderr, fmt, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void non_fatal(char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) va_start(list, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) vfprintf(stderr, fmt, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int start_ptraced_child(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int pid, n, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (pid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ptrace_child();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) else if (pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) fatal_perror("start_ptraced_child : fork failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) fatal_perror("check_ptrace : waitpid failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fatal("check_ptrace : expected SIGSTOP, got status = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* When testing for SYSEMU support, if it is one of the broken versions, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * must just avoid using sysemu, not panic, but only if SYSEMU features are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * broken.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * So only for SYSEMU features we test mustpanic, while normal host features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * must work anyway!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int stop_ptraced_child(int pid, int exitcode, int mustexit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int status, n, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) perror("stop_ptraced_child : ptrace failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) CATCH_EINTR(n = waitpid(pid, &status, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int exit_with = WEXITSTATUS(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (exit_with == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) non_fatal("check_ptrace : child exited with status 2. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "\nDisabling SYSEMU support.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) non_fatal("check_ptrace : child exited with exitcode %d, while "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "expecting %d; status 0x%x\n", exit_with,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) exitcode, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (mustexit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Changed only during early boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int force_sysemu_disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int __init nosysemu_cmd_param(char *str, int* add)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) force_sysemu_disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) __uml_setup("nosysemu", nosysemu_cmd_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "nosysemu\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) " Turns off syscall emulation patch for ptrace (SYSEMU).\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) " behaviour of ptrace() and helps reduce host context switch rates.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) " To make it work, you need a kernel patch for your host, too.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) " information.\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void __init check_sysemu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned long regs[MAX_REG_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int pid, n, status, count=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) os_info("Checking syscall emulation patch for ptrace...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) sysemu_supported = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pid = start_ptraced_child();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) fatal_perror("check_sysemu : wait failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fatal("check_sysemu : expected SIGTRAP, got status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) fatal_perror("check_sysemu : PTRACE_GETREGS failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (PT_SYSCALL_NR(regs) != __NR_getpid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) non_fatal("check_sysemu got system call number %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (n < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) non_fatal("check_sysemu : failed to modify system call "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) "return");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (stop_ptraced_child(pid, 0, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) goto fail_stopped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) sysemu_supported = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) os_info("OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) set_using_sysemu(!force_sysemu_disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) os_info("Checking advanced syscall emulation patch for ptrace...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pid = start_ptraced_child();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) (void *) PTRACE_O_TRACESYSGOOD) < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) fatal_perror("check_sysemu: PTRACE_OLDSETOPTIONS failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) fatal_perror("check_sysemu: wait failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (WIFSTOPPED(status) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) (WSTOPSIG(status) == (SIGTRAP|0x80))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) non_fatal("check_sysemu: SYSEMU_SINGLESTEP "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "doesn't singlestep");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) os_getpid());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) fatal_perror("check_sysemu : failed to modify "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "system call return");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) non_fatal("check_sysemu: expected SIGTRAP or "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "(SIGTRAP | 0x80), got status = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (stop_ptraced_child(pid, 0, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) goto fail_stopped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sysemu_supported = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) os_info("OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!force_sysemu_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) set_using_sysemu(sysemu_supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) stop_ptraced_child(pid, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) fail_stopped:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) non_fatal("missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void __init check_ptrace(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int pid, syscall, n, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) os_info("Checking that ptrace can change system call numbers...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pid = start_ptraced_child();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) (void *) PTRACE_O_TRACESYSGOOD) < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) fatal_perror("check_ptrace : ptrace failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) fatal_perror("check_ptrace : wait failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!WIFSTOPPED(status) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) (WSTOPSIG(status) != (SIGTRAP | 0x80)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) fatal("check_ptrace : expected (SIGTRAP|0x80), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) "got status = %d", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (syscall == __NR_getpid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) __NR_getppid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (n < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) fatal_perror("check_ptrace : failed to modify "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) "system call");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) stop_ptraced_child(pid, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) os_info("OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) check_sysemu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) extern void check_tmpexec(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void __init check_coredump_limit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct rlimit lim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int err = getrlimit(RLIMIT_CORE, &lim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) perror("Getting core dump limit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) os_info("Core dump limits :\n\tsoft - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (lim.rlim_cur == RLIM_INFINITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) os_info("NONE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) os_info("%llu\n", (unsigned long long)lim.rlim_cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) os_info("\thard - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (lim.rlim_max == RLIM_INFINITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) os_info("NONE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) os_info("%llu\n", (unsigned long long)lim.rlim_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) void __init os_early_checks(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* Print out the core dump limits early */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) check_coredump_limit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) check_ptrace();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Need to check this early because mmapping happens before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * kernel is running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) check_tmpexec();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pid = start_ptraced_child();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (init_pid_registers(pid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) fatal("Failed to initialize default registers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) stop_ptraced_child(pid, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int __init parse_iomem(char *str, int *add)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct iomem_region *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct stat64 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) char *file, *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int fd, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) driver = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) file = strchr(str,',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (file == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) os_warn("parse_iomem : failed to parse iomem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) *file = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) file++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) fd = open(file, O_RDWR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) perror("parse_iomem - Couldn't open io file");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (fstat64(fd, &buf) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) perror("parse_iomem - cannot stat_fd file");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) new = malloc(sizeof(*new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (new == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) perror("Couldn't allocate iomem_region struct");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *new = ((struct iomem_region) { .next = iomem_regions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .driver = driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .fd = fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .size = size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .phys = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .virt = 0 });
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) iomem_regions = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) iomem_size += new->size + UM_KERN_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }