^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 <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <signal.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 <termios.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 <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/utsname.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 <os.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) void stack_protections(unsigned long address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (mprotect((void *) address, UM_THREAD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) panic("protecting stack failed, errno = %d", errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int raw(int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct termios tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) CATCH_EINTR(err = tcgetattr(fd, &tt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) cfmakeraw(&tt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * XXX tcsetattr could have applied only some changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * (and cfmakeraw() is a set of changes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) void setup_machinename(char *machine_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct utsname host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) uname(&host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifdef UML_CONFIG_UML_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) # ifndef UML_CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!strcmp(host.machine, "x86_64")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) strcpy(machine_out, "i686");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) # else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!strcmp(host.machine, "i686")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) strcpy(machine_out, "x86_64");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) # endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) strcpy(machine_out, host.machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void setup_hostinfo(char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct utsname host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) uname(&host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) host.release, host.version, host.machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * We cannot use glibc's abort(). It makes use of tgkill() which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * has no effect within UML's kernel threads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * After that glibc would execute an invalid instruction to kill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * the calling process and UML crashes with SIGSEGV.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static inline void __attribute__ ((noreturn)) uml_abort(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) sigset_t sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) fflush(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sigprocmask(SIG_UNBLOCK, &sig, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) for (;;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (kill(getpid(), SIGABRT) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) exit(127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * UML helper threads must not handle SIGWINCH/INT/TERM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void os_fix_helper_signals(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) signal(SIGWINCH, SIG_IGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) signal(SIGINT, SIG_DFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) signal(SIGTERM, SIG_DFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) void os_dump_core(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) signal(SIGSEGV, SIG_DFL);
^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) * We are about to SIGTERM this entire process group to ensure that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * nothing is around to run after the kernel exits. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * kernel wants to abort, not die through SIGTERM, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * ignore it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) signal(SIGTERM, SIG_IGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) kill(0, SIGTERM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Most of the other processes associated with this UML are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * likely sTopped, so give them a SIGCONT so they see the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * SIGTERM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) kill(0, SIGCONT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Now, having sent signals to everyone but us, make sure they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * die by ptrace. Processes can survive what's been done to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * them so far - the mechanism I understand is receiving a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * SIGSEGV and segfaulting immediately upon return. There is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * always a SIGSEGV pending, and (I'm guessing) signals are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * processed in numeric order so the SIGTERM (signal 15 vs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * SIGSEGV being signal 11) is never handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Run a waitpid loop until we get some kind of error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Hopefully, it's ECHILD, but there's not a lot we can do if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * it's something else. Tell os_kill_ptraced_process not to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * wait for the child to report its death because there's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * nothing reasonable to do if that fails.
^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) while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) os_kill_ptraced_process(pid, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) uml_abort();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void um_early_printk(const char *s, unsigned int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) printf("%.*s", n, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int quiet_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int __init quiet_cmd_param(char *str, int *add)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) quiet_info = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) __uml_setup("quiet", quiet_cmd_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) "quiet\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) " Turns off information messages during boot.\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) void os_info(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (quiet_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) va_start(list, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) vfprintf(stderr, fmt, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void os_warn(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) va_start(list, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) vfprintf(stderr, fmt, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }