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