diff options
-rw-r--r-- | arch/um/os-Linux/start_up.c | 154 |
1 files changed, 92 insertions, 62 deletions
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 735d035a7f33..5178eba9afa5 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -73,6 +73,34 @@ static int ptrace_child(void *arg) | |||
73 | _exit(ret); | 73 | _exit(ret); |
74 | } | 74 | } |
75 | 75 | ||
76 | static void fatal_perror(char *str) | ||
77 | { | ||
78 | perror(str); | ||
79 | exit(1); | ||
80 | } | ||
81 | |||
82 | static void fatal(char *fmt, ...) | ||
83 | { | ||
84 | va_list list; | ||
85 | |||
86 | va_start(list, fmt); | ||
87 | vprintf(fmt, list); | ||
88 | va_end(list); | ||
89 | fflush(stdout); | ||
90 | |||
91 | exit(1); | ||
92 | } | ||
93 | |||
94 | static void non_fatal(char *fmt, ...) | ||
95 | { | ||
96 | va_list list; | ||
97 | |||
98 | va_start(list, fmt); | ||
99 | vprintf(fmt, list); | ||
100 | va_end(list); | ||
101 | fflush(stdout); | ||
102 | } | ||
103 | |||
76 | static int start_ptraced_child(void **stack_out) | 104 | static int start_ptraced_child(void **stack_out) |
77 | { | 105 | { |
78 | void *stack; | 106 | void *stack; |
@@ -82,16 +110,16 @@ static int start_ptraced_child(void **stack_out) | |||
82 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, | 110 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, |
83 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 111 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
84 | if(stack == MAP_FAILED) | 112 | if(stack == MAP_FAILED) |
85 | panic("check_ptrace : mmap failed, errno = %d", errno); | 113 | fatal_perror("check_ptrace : mmap failed"); |
86 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); | 114 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); |
87 | pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); | 115 | pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); |
88 | if(pid < 0) | 116 | if(pid < 0) |
89 | panic("start_ptraced_child : clone failed, errno = %d", errno); | 117 | fatal_perror("start_ptraced_child : clone failed"); |
90 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 118 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
91 | if(n < 0) | 119 | if(n < 0) |
92 | panic("check_ptrace : clone failed, errno = %d", errno); | 120 | fatal_perror("check_ptrace : clone failed"); |
93 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) | 121 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) |
94 | panic("check_ptrace : expected SIGSTOP, got status = %d", | 122 | fatal("check_ptrace : expected SIGSTOP, got status = %d", |
95 | status); | 123 | status); |
96 | 124 | ||
97 | *stack_out = stack; | 125 | *stack_out = stack; |
@@ -105,31 +133,30 @@ static int start_ptraced_child(void **stack_out) | |||
105 | * must work anyway! | 133 | * must work anyway! |
106 | */ | 134 | */ |
107 | static int stop_ptraced_child(int pid, void *stack, int exitcode, | 135 | static int stop_ptraced_child(int pid, void *stack, int exitcode, |
108 | int mustpanic) | 136 | int mustexit) |
109 | { | 137 | { |
110 | int status, n, ret = 0; | 138 | int status, n, ret = 0; |
111 | 139 | ||
112 | if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) | 140 | if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) |
113 | panic("check_ptrace : ptrace failed, errno = %d", errno); | 141 | fatal_perror("stop_ptraced_child : ptrace failed"); |
114 | CATCH_EINTR(n = waitpid(pid, &status, 0)); | 142 | CATCH_EINTR(n = waitpid(pid, &status, 0)); |
115 | if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { | 143 | if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { |
116 | int exit_with = WEXITSTATUS(status); | 144 | int exit_with = WEXITSTATUS(status); |
117 | if (exit_with == 2) | 145 | if (exit_with == 2) |
118 | printf("check_ptrace : child exited with status 2. " | 146 | non_fatal("check_ptrace : child exited with status 2. " |
119 | "Serious trouble happening! Try updating your " | 147 | "Serious trouble happening! Try updating " |
120 | "host skas patch!\nDisabling SYSEMU support."); | 148 | "your host skas patch!\nDisabling SYSEMU " |
121 | printf("check_ptrace : child exited with exitcode %d, while " | 149 | "support."); |
122 | "expecting %d; status 0x%x", exit_with, | 150 | non_fatal("check_ptrace : child exited with exitcode %d, while " |
123 | exitcode, status); | 151 | "expecting %d; status 0x%x\n", exit_with, |
124 | if (mustpanic) | 152 | exitcode, status); |
125 | panic("\n"); | 153 | if (mustexit) |
126 | else | 154 | exit(1); |
127 | printf("\n"); | ||
128 | ret = -1; | 155 | ret = -1; |
129 | } | 156 | } |
130 | 157 | ||
131 | if(munmap(stack, PAGE_SIZE) < 0) | 158 | if(munmap(stack, PAGE_SIZE) < 0) |
132 | panic("check_ptrace : munmap failed, errno = %d", errno); | 159 | fatal_perror("check_ptrace : munmap failed"); |
133 | return ret; | 160 | return ret; |
134 | } | 161 | } |
135 | 162 | ||
@@ -184,7 +211,7 @@ static void __init check_sysemu(void) | |||
184 | void *stack; | 211 | void *stack; |
185 | int pid, n, status, count=0; | 212 | int pid, n, status, count=0; |
186 | 213 | ||
187 | printf("Checking syscall emulation patch for ptrace..."); | 214 | non_fatal("Checking syscall emulation patch for ptrace..."); |
188 | sysemu_supported = 0; | 215 | sysemu_supported = 0; |
189 | pid = start_ptraced_child(&stack); | 216 | pid = start_ptraced_child(&stack); |
190 | 217 | ||
@@ -193,31 +220,30 @@ static void __init check_sysemu(void) | |||
193 | 220 | ||
194 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 221 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
195 | if (n < 0) | 222 | if (n < 0) |
196 | panic("check_sysemu : wait failed, errno = %d", errno); | 223 | fatal_perror("check_sysemu : wait failed"); |
197 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) | 224 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) |
198 | panic("check_sysemu : expected SIGTRAP, " | 225 | fatal("check_sysemu : expected SIGTRAP, got status = %d", |
199 | "got status = %d", status); | 226 | status); |
200 | 227 | ||
201 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, | 228 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, |
202 | os_getpid()); | 229 | os_getpid()); |
203 | if(n < 0) | 230 | if(n < 0) |
204 | panic("check_sysemu : failed to modify system " | 231 | fatal_perror("check_sysemu : failed to modify system call " |
205 | "call return, errno = %d", errno); | 232 | "return"); |
206 | 233 | ||
207 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) | 234 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) |
208 | goto fail_stopped; | 235 | goto fail_stopped; |
209 | 236 | ||
210 | sysemu_supported = 1; | 237 | sysemu_supported = 1; |
211 | printf("OK\n"); | 238 | non_fatal("OK\n"); |
212 | set_using_sysemu(!force_sysemu_disabled); | 239 | set_using_sysemu(!force_sysemu_disabled); |
213 | 240 | ||
214 | printf("Checking advanced syscall emulation patch for ptrace..."); | 241 | non_fatal("Checking advanced syscall emulation patch for ptrace..."); |
215 | pid = start_ptraced_child(&stack); | 242 | pid = start_ptraced_child(&stack); |
216 | 243 | ||
217 | if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, | 244 | if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, |
218 | (void *) PTRACE_O_TRACESYSGOOD) < 0) | 245 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) |
219 | panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", | 246 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); |
220 | errno); | ||
221 | 247 | ||
222 | while(1){ | 248 | while(1){ |
223 | count++; | 249 | count++; |
@@ -225,29 +251,30 @@ static void __init check_sysemu(void) | |||
225 | goto fail; | 251 | goto fail; |
226 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 252 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
227 | if(n < 0) | 253 | if(n < 0) |
228 | panic("check_ptrace : wait failed, errno = %d", errno); | 254 | fatal_perror("check_ptrace : wait failed"); |
255 | |||
229 | if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ | 256 | if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ |
230 | if (!count) | 257 | if (!count) |
231 | panic("check_ptrace : SYSEMU_SINGLESTEP " | 258 | fatal("check_ptrace : SYSEMU_SINGLESTEP " |
232 | "doesn't singlestep"); | 259 | "doesn't singlestep"); |
233 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, | 260 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, |
234 | os_getpid()); | 261 | os_getpid()); |
235 | if(n < 0) | 262 | if(n < 0) |
236 | panic("check_sysemu : failed to modify system " | 263 | fatal_perror("check_sysemu : failed to modify " |
237 | "call return, errno = %d", errno); | 264 | "system call return"); |
238 | break; | 265 | break; |
239 | } | 266 | } |
240 | else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) | 267 | else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) |
241 | count++; | 268 | count++; |
242 | else | 269 | else |
243 | panic("check_ptrace : expected SIGTRAP or " | 270 | fatal("check_ptrace : expected SIGTRAP or " |
244 | "(SIGTRAP|0x80), got status = %d", status); | 271 | "(SIGTRAP | 0x80), got status = %d", status); |
245 | } | 272 | } |
246 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) | 273 | if (stop_ptraced_child(pid, stack, 0, 0) < 0) |
247 | goto fail_stopped; | 274 | goto fail_stopped; |
248 | 275 | ||
249 | sysemu_supported = 2; | 276 | sysemu_supported = 2; |
250 | printf("OK\n"); | 277 | non_fatal("OK\n"); |
251 | 278 | ||
252 | if ( !force_sysemu_disabled ) | 279 | if ( !force_sysemu_disabled ) |
253 | set_using_sysemu(sysemu_supported); | 280 | set_using_sysemu(sysemu_supported); |
@@ -256,7 +283,7 @@ static void __init check_sysemu(void) | |||
256 | fail: | 283 | fail: |
257 | stop_ptraced_child(pid, stack, 1, 0); | 284 | stop_ptraced_child(pid, stack, 1, 0); |
258 | fail_stopped: | 285 | fail_stopped: |
259 | printf("missing\n"); | 286 | non_fatal("missing\n"); |
260 | } | 287 | } |
261 | 288 | ||
262 | static void __init check_ptrace(void) | 289 | static void __init check_ptrace(void) |
@@ -264,22 +291,25 @@ static void __init check_ptrace(void) | |||
264 | void *stack; | 291 | void *stack; |
265 | int pid, syscall, n, status; | 292 | int pid, syscall, n, status; |
266 | 293 | ||
267 | printf("Checking that ptrace can change system call numbers..."); | 294 | non_fatal("Checking that ptrace can change system call numbers..."); |
268 | pid = start_ptraced_child(&stack); | 295 | pid = start_ptraced_child(&stack); |
269 | 296 | ||
270 | if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) | 297 | if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, |
271 | panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno); | 298 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) |
299 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); | ||
272 | 300 | ||
273 | while(1){ | 301 | while(1){ |
274 | if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) | 302 | if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) |
275 | panic("check_ptrace : ptrace failed, errno = %d", | 303 | fatal_perror("check_ptrace : ptrace failed"); |
276 | errno); | 304 | |
277 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 305 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
278 | if(n < 0) | 306 | if(n < 0) |
279 | panic("check_ptrace : wait failed, errno = %d", errno); | 307 | fatal_perror("check_ptrace : wait failed"); |
280 | if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80))) | 308 | |
281 | panic("check_ptrace : expected (SIGTRAP|0x80), " | 309 | if(!WIFSTOPPED(status) || |
282 | "got status = %d", status); | 310 | (WSTOPSIG(status) != (SIGTRAP | 0x80))) |
311 | fatal("check_ptrace : expected (SIGTRAP|0x80), " | ||
312 | "got status = %d", status); | ||
283 | 313 | ||
284 | syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, | 314 | syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, |
285 | 0); | 315 | 0); |
@@ -287,13 +317,13 @@ static void __init check_ptrace(void) | |||
287 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, | 317 | n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, |
288 | __NR_getppid); | 318 | __NR_getppid); |
289 | if(n < 0) | 319 | if(n < 0) |
290 | panic("check_ptrace : failed to modify system " | 320 | fatal_perror("check_ptrace : failed to modify " |
291 | "call, errno = %d", errno); | 321 | "system call"); |
292 | break; | 322 | break; |
293 | } | 323 | } |
294 | } | 324 | } |
295 | stop_ptraced_child(pid, stack, 0, 1); | 325 | stop_ptraced_child(pid, stack, 0, 1); |
296 | printf("OK\n"); | 326 | non_fatal("OK\n"); |
297 | check_sysemu(); | 327 | check_sysemu(); |
298 | } | 328 | } |
299 | 329 | ||
@@ -352,22 +382,22 @@ static inline void check_skas3_ptrace_faultinfo(void) | |||
352 | void *stack; | 382 | void *stack; |
353 | int pid, n; | 383 | int pid, n; |
354 | 384 | ||
355 | printf(" - PTRACE_FAULTINFO..."); | 385 | non_fatal(" - PTRACE_FAULTINFO..."); |
356 | pid = start_ptraced_child(&stack); | 386 | pid = start_ptraced_child(&stack); |
357 | 387 | ||
358 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); | 388 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); |
359 | if (n < 0) { | 389 | if (n < 0) { |
360 | ptrace_faultinfo = 0; | 390 | ptrace_faultinfo = 0; |
361 | if(errno == EIO) | 391 | if(errno == EIO) |
362 | printf("not found\n"); | 392 | non_fatal("not found\n"); |
363 | else | 393 | else |
364 | perror("not found"); | 394 | perror("not found"); |
365 | } | 395 | } |
366 | else { | 396 | else { |
367 | if (!ptrace_faultinfo) | 397 | if (!ptrace_faultinfo) |
368 | printf("found but disabled on command line\n"); | 398 | non_fatal("found but disabled on command line\n"); |
369 | else | 399 | else |
370 | printf("found\n"); | 400 | non_fatal("found\n"); |
371 | } | 401 | } |
372 | 402 | ||
373 | init_registers(pid); | 403 | init_registers(pid); |
@@ -385,13 +415,13 @@ static inline void check_skas3_ptrace_ldt(void) | |||
385 | .ptr = ldtbuf, | 415 | .ptr = ldtbuf, |
386 | .bytecount = sizeof(ldtbuf)}; | 416 | .bytecount = sizeof(ldtbuf)}; |
387 | 417 | ||
388 | printf(" - PTRACE_LDT..."); | 418 | non_fatal(" - PTRACE_LDT..."); |
389 | pid = start_ptraced_child(&stack); | 419 | pid = start_ptraced_child(&stack); |
390 | 420 | ||
391 | n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); | 421 | n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); |
392 | if (n < 0) { | 422 | if (n < 0) { |
393 | if(errno == EIO) | 423 | if(errno == EIO) |
394 | printf("not found\n"); | 424 | non_fatal("not found\n"); |
395 | else { | 425 | else { |
396 | perror("not found"); | 426 | perror("not found"); |
397 | } | 427 | } |
@@ -399,9 +429,9 @@ static inline void check_skas3_ptrace_ldt(void) | |||
399 | } | 429 | } |
400 | else { | 430 | else { |
401 | if(ptrace_ldt) | 431 | if(ptrace_ldt) |
402 | printf("found\n"); | 432 | non_fatal("found\n"); |
403 | else | 433 | else |
404 | printf("found, but use is disabled\n"); | 434 | non_fatal("found, but use is disabled\n"); |
405 | } | 435 | } |
406 | 436 | ||
407 | stop_ptraced_child(pid, stack, 1, 1); | 437 | stop_ptraced_child(pid, stack, 1, 1); |
@@ -416,22 +446,22 @@ static inline void check_skas3_ptrace_ldt(void) | |||
416 | 446 | ||
417 | static inline void check_skas3_proc_mm(void) | 447 | static inline void check_skas3_proc_mm(void) |
418 | { | 448 | { |
419 | printf(" - /proc/mm..."); | 449 | non_fatal(" - /proc/mm..."); |
420 | if (access("/proc/mm", W_OK) < 0) { | 450 | if (access("/proc/mm", W_OK) < 0) { |
421 | proc_mm = 0; | 451 | proc_mm = 0; |
422 | printf("not found\n"); | 452 | perror("not found"); |
423 | } | 453 | } |
424 | else { | 454 | else { |
425 | if (!proc_mm) | 455 | if (!proc_mm) |
426 | printf("found but disabled on command line\n"); | 456 | non_fatal("found but disabled on command line\n"); |
427 | else | 457 | else |
428 | printf("found\n"); | 458 | non_fatal("found\n"); |
429 | } | 459 | } |
430 | } | 460 | } |
431 | 461 | ||
432 | int can_do_skas(void) | 462 | int can_do_skas(void) |
433 | { | 463 | { |
434 | printf("Checking for the skas3 patch in the host:\n"); | 464 | non_fatal("Checking for the skas3 patch in the host:\n"); |
435 | 465 | ||
436 | check_skas3_proc_mm(); | 466 | check_skas3_proc_mm(); |
437 | check_skas3_ptrace_faultinfo(); | 467 | check_skas3_ptrace_faultinfo(); |