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> | |
1ffb9164 | 16 | #include "kern_constants.h" |
5134d8fe JD |
17 | #include "os.h" |
18 | #include "user.h" | |
1da177e4 LT |
19 | |
20 | void stack_protections(unsigned long address) | |
21 | { | |
5134d8fe | 22 | if (mprotect((void *) address, UM_THREAD_SIZE, |
57598fd7 | 23 | PROT_READ | PROT_WRITE | PROT_EXEC) < 0) |
1da177e4 LT |
24 | panic("protecting stack failed, errno = %d", errno); |
25 | } | |
26 | ||
1da177e4 LT |
27 | int raw(int fd) |
28 | { | |
29 | struct termios tt; | |
30 | int err; | |
31 | ||
32 | CATCH_EINTR(err = tcgetattr(fd, &tt)); | |
5134d8fe | 33 | if (err < 0) |
b4fd310e | 34 | return -errno; |
1da177e4 LT |
35 | |
36 | cfmakeraw(&tt); | |
37 | ||
4fef0c10 | 38 | CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); |
5134d8fe | 39 | if (err < 0) |
b4fd310e | 40 | return -errno; |
1da177e4 | 41 | |
5134d8fe JD |
42 | /* |
43 | * XXX tcsetattr could have applied only some changes | |
44 | * (and cfmakeraw() is a set of changes) | |
45 | */ | |
57598fd7 | 46 | return 0; |
1da177e4 LT |
47 | } |
48 | ||
49 | void setup_machinename(char *machine_out) | |
50 | { | |
51 | struct utsname host; | |
52 | ||
53 | uname(&host); | |
69fada32 PBG |
54 | #ifdef UML_CONFIG_UML_X86 |
55 | # ifndef UML_CONFIG_64BIT | |
8e5cb35a PBG |
56 | if (!strcmp(host.machine, "x86_64")) { |
57 | strcpy(machine_out, "i686"); | |
58 | return; | |
59 | } | |
69fada32 PBG |
60 | # else |
61 | if (!strcmp(host.machine, "i686")) { | |
62 | strcpy(machine_out, "x86_64"); | |
63 | return; | |
64 | } | |
65 | # endif | |
8e5cb35a | 66 | #endif |
1da177e4 LT |
67 | strcpy(machine_out, host.machine); |
68 | } | |
69 | ||
b4ffb6ad | 70 | void setup_hostinfo(char *buf, int len) |
1da177e4 LT |
71 | { |
72 | struct utsname host; | |
73 | ||
74 | uname(&host); | |
b4ffb6ad JD |
75 | snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename, |
76 | host.release, host.version, host.machine); | |
1da177e4 LT |
77 | } |
78 | ||
b2db2199 RW |
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 | static inline void __attribute__ ((noreturn)) uml_abort(void) | |
86 | { | |
87 | sigset_t sig; | |
88 | ||
89 | fflush(NULL); | |
90 | ||
91 | if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT)) | |
92 | sigprocmask(SIG_UNBLOCK, &sig, 0); | |
93 | ||
94 | for (;;) | |
95 | if (kill(getpid(), SIGABRT) < 0) | |
96 | exit(127); | |
97 | } | |
98 | ||
63843c26 JD |
99 | void os_dump_core(void) |
100 | { | |
a24864a1 LW |
101 | int pid; |
102 | ||
63843c26 | 103 | signal(SIGSEGV, SIG_DFL); |
a24864a1 LW |
104 | |
105 | /* | |
106 | * We are about to SIGTERM this entire process group to ensure that | |
107 | * nothing is around to run after the kernel exits. The | |
108 | * kernel wants to abort, not die through SIGTERM, so we | |
109 | * ignore it here. | |
110 | */ | |
111 | ||
112 | signal(SIGTERM, SIG_IGN); | |
113 | kill(0, SIGTERM); | |
114 | /* | |
115 | * Most of the other processes associated with this UML are | |
116 | * likely sTopped, so give them a SIGCONT so they see the | |
117 | * SIGTERM. | |
118 | */ | |
119 | kill(0, SIGCONT); | |
120 | ||
121 | /* | |
122 | * Now, having sent signals to everyone but us, make sure they | |
123 | * die by ptrace. Processes can survive what's been done to | |
124 | * them so far - the mechanism I understand is receiving a | |
125 | * SIGSEGV and segfaulting immediately upon return. There is | |
126 | * always a SIGSEGV pending, and (I'm guessing) signals are | |
127 | * processed in numeric order so the SIGTERM (signal 15 vs | |
128 | * SIGSEGV being signal 11) is never handled. | |
129 | * | |
130 | * Run a waitpid loop until we get some kind of error. | |
131 | * Hopefully, it's ECHILD, but there's not a lot we can do if | |
132 | * it's something else. Tell os_kill_ptraced_process not to | |
133 | * wait for the child to report its death because there's | |
134 | * nothing reasonable to do if that fails. | |
135 | */ | |
136 | ||
4dbed85a | 137 | while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) |
a24864a1 LW |
138 | os_kill_ptraced_process(pid, 0); |
139 | ||
b2db2199 | 140 | uml_abort(); |
63843c26 | 141 | } |