1 /* 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdarg.h> 9 #include <unistd.h> 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <sched.h> 13 #include <signal.h> 14 #include <string.h> 15 #include <sys/mman.h> 16 #include <sys/ptrace.h> 17 #include <sys/stat.h> 18 #include <sys/wait.h> 19 #include <asm/unistd.h> 20 #include "init.h" 21 #include "kern_constants.h" 22 #include "os.h" 23 #include "mem_user.h" 24 #include "ptrace_user.h" 25 #include "registers.h" 26 #include "skas_ptrace.h" 27 28 static int ptrace_child(void *arg) 29 { 30 int ret; 31 int pid = os_getpid(), ppid = getppid(); 32 int sc_result; 33 34 change_sig(SIGWINCH, 0); 35 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { 36 perror("ptrace"); 37 os_kill_process(pid, 0); 38 } 39 kill(pid, SIGSTOP); 40 41 /* 42 * This syscall will be intercepted by the parent. Don't call more than 43 * once, please. 44 */ 45 sc_result = os_getpid(); 46 47 if (sc_result == pid) 48 /* Nothing modified by the parent, we are running normally. */ 49 ret = 1; 50 else if (sc_result == ppid) 51 /* 52 * Expected in check_ptrace and check_sysemu when they succeed 53 * in modifying the stack frame 54 */ 55 ret = 0; 56 else 57 /* Serious trouble! This could be caused by a bug in host 2.6 58 * SKAS3/2.6 patch before release -V6, together with a bug in 59 * the UML code itself. 60 */ 61 ret = 2; 62 _exit(ret); 63 } 64 65 static void fatal_perror(char *str) 66 { 67 perror(str); 68 exit(1); 69 } 70 71 static void fatal(char *fmt, ...) 72 { 73 va_list list; 74 75 va_start(list, fmt); 76 vprintf(fmt, list); 77 va_end(list); 78 fflush(stdout); 79 80 exit(1); 81 } 82 83 static void non_fatal(char *fmt, ...) 84 { 85 va_list list; 86 87 va_start(list, fmt); 88 vprintf(fmt, list); 89 va_end(list); 90 fflush(stdout); 91 } 92 93 static int start_ptraced_child(void **stack_out) 94 { 95 void *stack; 96 unsigned long sp; 97 int pid, n, status; 98 99 stack = mmap(NULL, UM_KERN_PAGE_SIZE, 100 PROT_READ | PROT_WRITE | PROT_EXEC, 101 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 102 if (stack == MAP_FAILED) 103 fatal_perror("check_ptrace : mmap failed"); 104 105 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); 106 pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); 107 if (pid < 0) 108 fatal_perror("start_ptraced_child : clone failed"); 109 110 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 111 if (n < 0) 112 fatal_perror("check_ptrace : clone failed"); 113 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 114 fatal("check_ptrace : expected SIGSTOP, got status = %d", 115 status); 116 117 *stack_out = stack; 118 return pid; 119 } 120 121 /* When testing for SYSEMU support, if it is one of the broken versions, we 122 * must just avoid using sysemu, not panic, but only if SYSEMU features are 123 * broken. 124 * So only for SYSEMU features we test mustpanic, while normal host features 125 * must work anyway! 126 */ 127 static int stop_ptraced_child(int pid, void *stack, int exitcode, 128 int mustexit) 129 { 130 int status, n, ret = 0; 131 132 if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) 133 fatal_perror("stop_ptraced_child : ptrace failed"); 134 CATCH_EINTR(n = waitpid(pid, &status, 0)); 135 if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { 136 int exit_with = WEXITSTATUS(status); 137 if (exit_with == 2) 138 non_fatal("check_ptrace : child exited with status 2. " 139 "\nDisabling SYSEMU support.\n"); 140 non_fatal("check_ptrace : child exited with exitcode %d, while " 141 "expecting %d; status 0x%x\n", exit_with, 142 exitcode, status); 143 if (mustexit) 144 exit(1); 145 ret = -1; 146 } 147 148 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) 149 fatal_perror("check_ptrace : munmap failed"); 150 return ret; 151 } 152 153 /* Changed only during early boot */ 154 int ptrace_faultinfo = 1; 155 int ptrace_ldt = 1; 156 int proc_mm = 1; 157 int skas_needs_stub = 0; 158 159 static int __init skas0_cmd_param(char *str, int* add) 160 { 161 ptrace_faultinfo = proc_mm = 0; 162 return 0; 163 } 164 165 /* The two __uml_setup would conflict, without this stupid alias. */ 166 167 static int __init mode_skas0_cmd_param(char *str, int* add) 168 __attribute__((alias("skas0_cmd_param"))); 169 170 __uml_setup("skas0", skas0_cmd_param, 171 "skas0\n" 172 " Disables SKAS3 usage, so that SKAS0 is used, unless \n" 173 " you specify mode=tt.\n\n"); 174 175 __uml_setup("mode=skas0", mode_skas0_cmd_param, 176 "mode=skas0\n" 177 " Disables SKAS3 usage, so that SKAS0 is used, unless you \n" 178 " specify mode=tt. Note that this was recently added - on \n" 179 " older kernels you must use simply \"skas0\".\n\n"); 180 181 /* Changed only during early boot */ 182 static int force_sysemu_disabled = 0; 183 184 static int __init nosysemu_cmd_param(char *str, int* add) 185 { 186 force_sysemu_disabled = 1; 187 return 0; 188 } 189 190 __uml_setup("nosysemu", nosysemu_cmd_param, 191 "nosysemu\n" 192 " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n" 193 " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n" 194 " behaviour of ptrace() and helps reducing host context switch rate.\n" 195 " To make it working, you need a kernel patch for your host, too.\n" 196 " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n" 197 " information.\n\n"); 198 199 static void __init check_sysemu(void) 200 { 201 void *stack; 202 unsigned long regs[MAX_REG_NR]; 203 int pid, n, status, count=0; 204 205 non_fatal("Checking syscall emulation patch for ptrace..."); 206 sysemu_supported = 0; 207 pid = start_ptraced_child(&stack); 208 209 if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) 210 goto fail; 211 212 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 213 if (n < 0) 214 fatal_perror("check_sysemu : wait failed"); 215 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) 216 fatal("check_sysemu : expected SIGTRAP, got status = %d", 217 status); 218 219 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 220 fatal_perror("check_sysemu : PTRACE_GETREGS failed"); 221 if (PT_SYSCALL_NR(regs) != __NR_getpid) { 222 non_fatal("check_sysemu got system call number %d, " 223 "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); 224 goto fail; 225 } 226 227 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); 228 if (n < 0) { 229 non_fatal("check_sysemu : failed to modify system call " 230 "return"); 231 goto fail; 232 } 233 234 if (stop_ptraced_child(pid, stack, 0, 0) < 0) 235 goto fail_stopped; 236 237 sysemu_supported = 1; 238 non_fatal("OK\n"); 239 set_using_sysemu(!force_sysemu_disabled); 240 241 non_fatal("Checking advanced syscall emulation patch for ptrace..."); 242 pid = start_ptraced_child(&stack); 243 244 if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 245 (void *) PTRACE_O_TRACESYSGOOD) < 0)) 246 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); 247 248 while (1) { 249 count++; 250 if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) 251 goto fail; 252 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 253 if (n < 0) 254 fatal_perror("check_ptrace : wait failed"); 255 256 if (WIFSTOPPED(status) && 257 (WSTOPSIG(status) == (SIGTRAP|0x80))) { 258 if (!count) 259 fatal("check_ptrace : SYSEMU_SINGLESTEP " 260 "doesn't singlestep"); 261 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, 262 os_getpid()); 263 if (n < 0) 264 fatal_perror("check_sysemu : failed to modify " 265 "system call return"); 266 break; 267 } 268 else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) 269 count++; 270 else 271 fatal("check_ptrace : expected SIGTRAP or " 272 "(SIGTRAP | 0x80), got status = %d", status); 273 } 274 if (stop_ptraced_child(pid, stack, 0, 0) < 0) 275 goto fail_stopped; 276 277 sysemu_supported = 2; 278 non_fatal("OK\n"); 279 280 if (!force_sysemu_disabled) 281 set_using_sysemu(sysemu_supported); 282 return; 283 284 fail: 285 stop_ptraced_child(pid, stack, 1, 0); 286 fail_stopped: 287 non_fatal("missing\n"); 288 } 289 290 static void __init check_ptrace(void) 291 { 292 void *stack; 293 int pid, syscall, n, status; 294 295 non_fatal("Checking that ptrace can change system call numbers..."); 296 pid = start_ptraced_child(&stack); 297 298 if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 299 (void *) PTRACE_O_TRACESYSGOOD) < 0)) 300 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); 301 302 while (1) { 303 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) 304 fatal_perror("check_ptrace : ptrace failed"); 305 306 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 307 if (n < 0) 308 fatal_perror("check_ptrace : wait failed"); 309 310 if (!WIFSTOPPED(status) || 311 (WSTOPSIG(status) != (SIGTRAP | 0x80))) 312 fatal("check_ptrace : expected (SIGTRAP|0x80), " 313 "got status = %d", status); 314 315 syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 316 0); 317 if (syscall == __NR_getpid) { 318 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, 319 __NR_getppid); 320 if (n < 0) 321 fatal_perror("check_ptrace : failed to modify " 322 "system call"); 323 break; 324 } 325 } 326 stop_ptraced_child(pid, stack, 0, 1); 327 non_fatal("OK\n"); 328 check_sysemu(); 329 } 330 331 extern void check_tmpexec(void); 332 333 static void __init check_coredump_limit(void) 334 { 335 struct rlimit lim; 336 int err = getrlimit(RLIMIT_CORE, &lim); 337 338 if (err) { 339 perror("Getting core dump limit"); 340 return; 341 } 342 343 printf("Core dump limits :\n\tsoft - "); 344 if (lim.rlim_cur == RLIM_INFINITY) 345 printf("NONE\n"); 346 else printf("%lu\n", lim.rlim_cur); 347 348 printf("\thard - "); 349 if (lim.rlim_max == RLIM_INFINITY) 350 printf("NONE\n"); 351 else printf("%lu\n", lim.rlim_max); 352 } 353 354 void __init os_early_checks(void) 355 { 356 /* Print out the core dump limits early */ 357 check_coredump_limit(); 358 359 check_ptrace(); 360 361 /* Need to check this early because mmapping happens before the 362 * kernel is running. 363 */ 364 check_tmpexec(); 365 } 366 367 static int __init noprocmm_cmd_param(char *str, int* add) 368 { 369 proc_mm = 0; 370 return 0; 371 } 372 373 __uml_setup("noprocmm", noprocmm_cmd_param, 374 "noprocmm\n" 375 " Turns off usage of /proc/mm, even if host supports it.\n" 376 " To support /proc/mm, the host needs to be patched using\n" 377 " the current skas3 patch.\n\n"); 378 379 static int __init noptracefaultinfo_cmd_param(char *str, int* add) 380 { 381 ptrace_faultinfo = 0; 382 return 0; 383 } 384 385 __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, 386 "noptracefaultinfo\n" 387 " Turns off usage of PTRACE_FAULTINFO, even if host supports\n" 388 " it. To support PTRACE_FAULTINFO, the host needs to be patched\n" 389 " using the current skas3 patch.\n\n"); 390 391 static int __init noptraceldt_cmd_param(char *str, int* add) 392 { 393 ptrace_ldt = 0; 394 return 0; 395 } 396 397 __uml_setup("noptraceldt", noptraceldt_cmd_param, 398 "noptraceldt\n" 399 " Turns off usage of PTRACE_LDT, even if host supports it.\n" 400 " To support PTRACE_LDT, the host needs to be patched using\n" 401 " the current skas3 patch.\n\n"); 402 403 static inline void check_skas3_ptrace_faultinfo(void) 404 { 405 struct ptrace_faultinfo fi; 406 void *stack; 407 int pid, n; 408 409 non_fatal(" - PTRACE_FAULTINFO..."); 410 pid = start_ptraced_child(&stack); 411 412 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); 413 if (n < 0) { 414 ptrace_faultinfo = 0; 415 if (errno == EIO) 416 non_fatal("not found\n"); 417 else 418 perror("not found"); 419 } 420 else { 421 if (!ptrace_faultinfo) 422 non_fatal("found but disabled on command line\n"); 423 else 424 non_fatal("found\n"); 425 } 426 427 init_registers(pid); 428 stop_ptraced_child(pid, stack, 1, 1); 429 } 430 431 static inline void check_skas3_ptrace_ldt(void) 432 { 433 #ifdef PTRACE_LDT 434 void *stack; 435 int pid, n; 436 unsigned char ldtbuf[40]; 437 struct ptrace_ldt ldt_op = (struct ptrace_ldt) { 438 .func = 2, /* read default ldt */ 439 .ptr = ldtbuf, 440 .bytecount = sizeof(ldtbuf)}; 441 442 non_fatal(" - PTRACE_LDT..."); 443 pid = start_ptraced_child(&stack); 444 445 n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); 446 if (n < 0) { 447 if (errno == EIO) 448 non_fatal("not found\n"); 449 else { 450 perror("not found"); 451 } 452 ptrace_ldt = 0; 453 } 454 else { 455 if (ptrace_ldt) 456 non_fatal("found\n"); 457 else 458 non_fatal("found, but use is disabled\n"); 459 } 460 461 stop_ptraced_child(pid, stack, 1, 1); 462 #else 463 /* PTRACE_LDT might be disabled via cmdline option. 464 * We want to override this, else we might use the stub 465 * without real need 466 */ 467 ptrace_ldt = 1; 468 #endif 469 } 470 471 static inline void check_skas3_proc_mm(void) 472 { 473 non_fatal(" - /proc/mm..."); 474 if (access("/proc/mm", W_OK) < 0) { 475 proc_mm = 0; 476 perror("not found"); 477 } 478 else if (!proc_mm) 479 non_fatal("found but disabled on command line\n"); 480 else non_fatal("found\n"); 481 } 482 483 int can_do_skas(void) 484 { 485 non_fatal("Checking for the skas3 patch in the host:\n"); 486 487 check_skas3_proc_mm(); 488 check_skas3_ptrace_faultinfo(); 489 check_skas3_ptrace_ldt(); 490 491 if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) 492 skas_needs_stub = 1; 493 494 return 1; 495 } 496 497 int __init parse_iomem(char *str, int *add) 498 { 499 struct iomem_region *new; 500 struct stat64 buf; 501 char *file, *driver; 502 int fd, size; 503 504 driver = str; 505 file = strchr(str,','); 506 if (file == NULL) { 507 printf("parse_iomem : failed to parse iomem\n"); 508 goto out; 509 } 510 *file = '\0'; 511 file++; 512 fd = open(file, O_RDWR, 0); 513 if (fd < 0) { 514 os_print_error(fd, "parse_iomem - Couldn't open io file"); 515 goto out; 516 } 517 518 if (fstat64(fd, &buf) < 0) { 519 perror("parse_iomem - cannot stat_fd file"); 520 goto out_close; 521 } 522 523 new = malloc(sizeof(*new)); 524 if (new == NULL) { 525 perror("Couldn't allocate iomem_region struct"); 526 goto out_close; 527 } 528 529 size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); 530 531 *new = ((struct iomem_region) { .next = iomem_regions, 532 .driver = driver, 533 .fd = fd, 534 .size = size, 535 .phys = 0, 536 .virt = 0 }); 537 iomem_regions = new; 538 iomem_size += new->size + UM_KERN_PAGE_SIZE; 539 540 return 0; 541 out_close: 542 close(fd); 543 out: 544 return 1; 545 } 546