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