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