aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/os-Linux/start_up.c154
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
76static void fatal_perror(char *str)
77{
78 perror(str);
79 exit(1);
80}
81
82static 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
94static 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
76static int start_ptraced_child(void **stack_out) 104static 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 */
107static int stop_ptraced_child(int pid, void *stack, int exitcode, 135static 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)
256fail: 283fail:
257 stop_ptraced_child(pid, stack, 1, 0); 284 stop_ptraced_child(pid, stack, 1, 0);
258fail_stopped: 285fail_stopped:
259 printf("missing\n"); 286 non_fatal("missing\n");
260} 287}
261 288
262static void __init check_ptrace(void) 289static 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
417static inline void check_skas3_proc_mm(void) 447static 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
432int can_do_skas(void) 462int 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();