]>
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 | ||
63843c26 JD |
97 | void os_dump_core(void) |
98 | { | |
a24864a1 LW |
99 | int pid; |
100 | ||
63843c26 | 101 | signal(SIGSEGV, SIG_DFL); |
a24864a1 LW |
102 | |
103 | /* | |
104 | * We are about to SIGTERM this entire process group to ensure that | |
105 | * nothing is around to run after the kernel exits. The | |
106 | * kernel wants to abort, not die through SIGTERM, so we | |
107 | * ignore it here. | |
108 | */ | |
109 | ||
110 | signal(SIGTERM, SIG_IGN); | |
111 | kill(0, SIGTERM); | |
112 | /* | |
113 | * Most of the other processes associated with this UML are | |
114 | * likely sTopped, so give them a SIGCONT so they see the | |
115 | * SIGTERM. | |
116 | */ | |
117 | kill(0, SIGCONT); | |
118 | ||
119 | /* | |
120 | * Now, having sent signals to everyone but us, make sure they | |
121 | * die by ptrace. Processes can survive what's been done to | |
122 | * them so far - the mechanism I understand is receiving a | |
123 | * SIGSEGV and segfaulting immediately upon return. There is | |
124 | * always a SIGSEGV pending, and (I'm guessing) signals are | |
125 | * processed in numeric order so the SIGTERM (signal 15 vs | |
126 | * SIGSEGV being signal 11) is never handled. | |
127 | * | |
128 | * Run a waitpid loop until we get some kind of error. | |
129 | * Hopefully, it's ECHILD, but there's not a lot we can do if | |
130 | * it's something else. Tell os_kill_ptraced_process not to | |
131 | * wait for the child to report its death because there's | |
132 | * nothing reasonable to do if that fails. | |
133 | */ | |
134 | ||
4dbed85a | 135 | while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) |
a24864a1 LW |
136 | os_kill_ptraced_process(pid, 0); |
137 | ||
b2db2199 | 138 | uml_abort(); |
63843c26 | 139 | } |
d634f194 RW |
140 | |
141 | void um_early_printk(const char *s, unsigned int n) | |
142 | { | |
143 | printf("%.*s", n, s); | |
144 | } |