160d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov/* 2ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdio.h> 70f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike#include <stdlib.h> 8ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <stdarg.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <unistd.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 11ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <fcntl.h> 12ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <sched.h> 13ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <signal.h> 14ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <string.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/mman.h> 16ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <sys/stat.h> 17ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <sys/wait.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unistd.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "init.h" 20ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "os.h" 21ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "mem_user.h" 22ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "ptrace_user.h" 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "registers.h" 2453c258787427ea43ebfa76fefa6534cae507e521Jeff Dike#include "skas.h" 25ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "skas_ptrace.h" 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27626c59f5edb284027bfe25cc15e7de2f532090b5WANG Congstatic void ptrace_child(void) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 30512b6fb1c14d4c34f23a3419b0789ad01914a899Jeff Dike /* Calling os_getpid because some libcs cached getpid incorrectly */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pid = os_getpid(), ppid = getppid(); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sc_result; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34626c59f5edb284027bfe25cc15e7de2f532090b5WANG Cong if (change_sig(SIGWINCH, 0) < 0 || 35626c59f5edb284027bfe25cc15e7de2f532090b5WANG Cong ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror("ptrace"); 37512b6fb1c14d4c34f23a3419b0789ad01914a899Jeff Dike kill(pid, SIGKILL); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3973c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike kill(pid, SIGSTOP); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 42ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * This syscall will be intercepted by the parent. Don't call more than 43ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * once, please. 44ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc_result = os_getpid(); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sc_result == pid) 48ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* Nothing modified by the parent, we are running normally. */ 49ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike ret = 1; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (sc_result == ppid) 51ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 52ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Expected in check_ptrace and check_sysemu when they succeed 53ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * in modifying the stack frame 54ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike */ 55ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike ret = 0; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 57ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* Serious trouble! This could be caused by a bug in host 2.6 58ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * SKAS3/2.6 patch before release -V6, together with a bug in 59ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * the UML code itself. 60ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike */ 61ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike ret = 2; 62bf8fde785b872282e7e86d9ea8a9c4e543985bb3Jeff Dike 63bf8fde785b872282e7e86d9ea8a9c4e543985bb3Jeff Dike exit(ret); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 66c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddfWANG Congstatic void fatal_perror(const char *str) 673a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike{ 683a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike perror(str); 693a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike exit(1); 703a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike} 713a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 723a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dikestatic void fatal(char *fmt, ...) 733a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike{ 743a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_list list; 753a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 763a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_start(list, fmt); 77626c59f5edb284027bfe25cc15e7de2f532090b5WANG Cong vfprintf(stderr, fmt, list); 783a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_end(list); 793a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 803a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike exit(1); 813a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike} 823a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 833a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dikestatic void non_fatal(char *fmt, ...) 843a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike{ 853a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_list list; 863a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 873a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_start(list, fmt); 88626c59f5edb284027bfe25cc15e7de2f532090b5WANG Cong vfprintf(stderr, fmt, list); 893a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike va_end(list); 903a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike} 913a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 923cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dikestatic int start_ptraced_child(void) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pid, n, status; 9560d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov 963cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = fork(); 973cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike if (pid == 0) 983cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike ptrace_child(); 993cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike else if (pid < 0) 1003cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike fatal_perror("start_ptraced_child : fork failed"); 101ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 103ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) 1043cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike fatal_perror("check_ptrace : waitpid failed"); 105ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 1063a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal("check_ptrace : expected SIGSTOP, got status = %d", 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status); 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1099eae9b132cd2cebf98cc45550049d421302b9abaJeff Dike return pid; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11260d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov/* When testing for SYSEMU support, if it is one of the broken versions, we 11360d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov * must just avoid using sysemu, not panic, but only if SYSEMU features are 11460d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov * broken. 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So only for SYSEMU features we test mustpanic, while normal host features 11660d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov * must work anyway! 11760d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov */ 1183cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dikestatic int stop_ptraced_child(int pid, int exitcode, int mustexit) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status, n, ret = 0; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 122f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) { 123f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike perror("stop_ptraced_child : ptrace failed"); 124f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike return -1; 125f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike } 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(n = waitpid(pid, &status, 0)); 127ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int exit_with = WEXITSTATUS(status); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exit_with == 2) 1303a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("check_ptrace : child exited with status 2. " 131cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike "\nDisabling SYSEMU support.\n"); 1323a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("check_ptrace : child exited with exitcode %d, while " 1333a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike "expecting %d; status 0x%x\n", exit_with, 1343a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike exitcode, status); 1353a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike if (mustexit) 1363a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike exit(1); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -1; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1437242a4005d1c496bc1140d56a0d898cde1b3e3f6Jeff Dike/* Changed only during early boot */ 14453c258787427ea43ebfa76fefa6534cae507e521Jeff Dikeint ptrace_faultinfo; 14553c258787427ea43ebfa76fefa6534cae507e521Jeff Dikestatic int disable_ptrace_faultinfo; 14653c258787427ea43ebfa76fefa6534cae507e521Jeff Dike 14753c258787427ea43ebfa76fefa6534cae507e521Jeff Dikeint ptrace_ldt; 14853c258787427ea43ebfa76fefa6534cae507e521Jeff Dikestatic int disable_ptrace_ldt; 14953c258787427ea43ebfa76fefa6534cae507e521Jeff Dike 15053c258787427ea43ebfa76fefa6534cae507e521Jeff Dikeint proc_mm; 15153c258787427ea43ebfa76fefa6534cae507e521Jeff Dikestatic int disable_proc_mm; 15253c258787427ea43ebfa76fefa6534cae507e521Jeff Dike 15353c258787427ea43ebfa76fefa6534cae507e521Jeff Dikeint have_switch_mm; 15453c258787427ea43ebfa76fefa6534cae507e521Jeff Dikestatic int disable_switch_mm; 15553c258787427ea43ebfa76fefa6534cae507e521Jeff Dike 15653c258787427ea43ebfa76fefa6534cae507e521Jeff Dikeint skas_needs_stub; 157cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrusso 158cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrussostatic int __init skas0_cmd_param(char *str, int* add) 159cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrusso{ 16053c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_ptrace_faultinfo = 1; 16153c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_ptrace_ldt = 1; 16253c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_proc_mm = 1; 16353c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_switch_mm = 1; 16453c258787427ea43ebfa76fefa6534cae507e521Jeff Dike 165cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrusso return 0; 166cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrusso} 167cb66504d65e54210d7dc55a0027d309ca5f51f83Paolo 'Blaisorblade' Giarrusso 1689e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso/* The two __uml_setup would conflict, without this stupid alias. */ 1699e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso 1709e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrussostatic int __init mode_skas0_cmd_param(char *str, int* add) 1719e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso __attribute__((alias("skas0_cmd_param"))); 1729e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso 17360d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov__uml_setup("skas0", skas0_cmd_param, 17453c258787427ea43ebfa76fefa6534cae507e521Jeff Dike"skas0\n" 17553c258787427ea43ebfa76fefa6534cae507e521Jeff Dike" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); 17660d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov 1779e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso__uml_setup("mode=skas0", mode_skas0_cmd_param, 17853c258787427ea43ebfa76fefa6534cae507e521Jeff Dike"mode=skas0\n" 17953c258787427ea43ebfa76fefa6534cae507e521Jeff Dike" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); 1809e3d862e5c341c59b673c9cadd64210ca03cb41ePaolo 'Blaisorblade' Giarrusso 1817242a4005d1c496bc1140d56a0d898cde1b3e3f6Jeff Dike/* Changed only during early boot */ 18260d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapovstatic int force_sysemu_disabled = 0; 18360d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init nosysemu_cmd_param(char *str, int* add) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sysemu_disabled = 1; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__uml_setup("nosysemu", nosysemu_cmd_param, 19160d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov"nosysemu\n" 19260d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" Turns off syscall emulation patch for ptrace (SYSEMU) on.\n" 19360d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n" 19460d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" behaviour of ptrace() and helps reducing host context switch rate.\n" 19560d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" To make it working, you need a kernel patch for your host, too.\n" 19660d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n" 19760d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov" information.\n\n"); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init check_sysemu(void) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 201cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike unsigned long regs[MAX_REG_NR]; 2029eae9b132cd2cebf98cc45550049d421302b9abaJeff Dike int pid, n, status, count=0; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2043a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("Checking syscall emulation patch for ptrace..."); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysemu_supported = 0; 2063cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = start_ptraced_child(); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 208ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n < 0) 2133a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_sysemu : wait failed"); 214ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) 215f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike fatal("check_sysemu : expected SIGTRAP, got status = %d\n", 2163a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike status); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 218ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 219cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike fatal_perror("check_sysemu : PTRACE_GETREGS failed"); 220ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (PT_SYSCALL_NR(regs) != __NR_getpid) { 221cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike non_fatal("check_sysemu got system call number %d, " 222cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); 223cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike goto fail; 224cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike } 225cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike 226966e803ab12538faf2b236dbe83f7fb796a031d6Al Viro n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); 227ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) { 228cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike non_fatal("check_sysemu : failed to modify system call " 229cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike "return"); 230cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike goto fail; 231cf6acedbeac17dea1c1eed85048a72e188f3f768Jeff Dike } 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2333cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike if (stop_ptraced_child(pid, 0, 0) < 0) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail_stopped; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysemu_supported = 1; 2373a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("OK\n"); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_using_sysemu(!force_sysemu_disabled); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2403a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("Checking advanced syscall emulation patch for ptrace..."); 2413cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = start_ptraced_child(); 242f9dfefe423a7633d81310c7b06c5566c74f9167bBodo Stroesser 243ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 2443a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike (void *) PTRACE_O_TRACESYSGOOD) < 0)) 2455062910a06ee979002edbf58ab65481c81242df4WANG Cong fatal_perror("check_sysemu: PTRACE_OLDSETOPTIONS failed"); 246f9dfefe423a7633d81310c7b06c5566c74f9167bBodo Stroesser 247ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike while (1) { 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count++; 249ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 252ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) 2535062910a06ee979002edbf58ab65481c81242df4WANG Cong fatal_perror("check_sysemu: wait failed"); 2543a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 255ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (WIFSTOPPED(status) && 256ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike (WSTOPSIG(status) == (SIGTRAP|0x80))) { 257f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike if (!count) { 2585062910a06ee979002edbf58ab65481c81242df4WANG Cong non_fatal("check_sysemu: SYSEMU_SINGLESTEP " 259f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike "doesn't singlestep"); 260f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike goto fail; 261f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike } 262966e803ab12538faf2b236dbe83f7fb796a031d6Al Viro n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds os_getpid()); 264ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) 2653a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_sysemu : failed to modify " 2663a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike "system call return"); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 269ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) 270f9dfefe423a7633d81310c7b06c5566c74f9167bBodo Stroesser count++; 271f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike else { 2725062910a06ee979002edbf58ab65481c81242df4WANG Cong non_fatal("check_sysemu: expected SIGTRAP or " 273f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike "(SIGTRAP | 0x80), got status = %d\n", 274f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike status); 275f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike goto fail; 276f1ef9167ca4494a8c6d71d0031c73e9c8841eaddJeff Dike } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2783cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike if (stop_ptraced_child(pid, 0, 0) < 0) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail_stopped; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysemu_supported = 2; 2823a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("OK\n"); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 284ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!force_sysemu_disabled) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_using_sysemu(sysemu_supported); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail: 2893cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike stop_ptraced_child(pid, 1, 0); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail_stopped: 2913a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("missing\n"); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29460d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapovstatic void __init check_ptrace(void) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pid, syscall, n, status; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2983a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("Checking that ptrace can change system call numbers..."); 2993cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = start_ptraced_child(); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 3023a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike (void *) PTRACE_O_TRACESYSGOOD) < 0)) 3033a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 305ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike while (1) { 306ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) 3073a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_ptrace : ptrace failed"); 3083a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 310ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) 3113a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_ptrace : wait failed"); 3123a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike 313ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!WIFSTOPPED(status) || 3143a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike (WSTOPSIG(status) != (SIGTRAP | 0x80))) 3153a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal("check_ptrace : expected (SIGTRAP|0x80), " 3163a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike "got status = %d", status); 31760d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov 318966e803ab12538faf2b236dbe83f7fb796a031d6Al Viro syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0); 320ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (syscall == __NR_getpid) { 321966e803ab12538faf2b236dbe83f7fb796a031d6Al Viro n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __NR_getppid); 323ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (n < 0) 3243a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike fatal_perror("check_ptrace : failed to modify " 3253a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike "system call"); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3293cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike stop_ptraced_child(pid, 0, 1); 3303a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("OK\n"); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds check_sysemu(); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 334966a082f80a073af1564c5ed6313ef2f0587dde3Rob Landleyextern void check_tmpexec(void); 3350f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 33636e454630473caa178bcbc4982ed6a68cf002e95Jeff Dikestatic void __init check_coredump_limit(void) 3371d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike{ 3381d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike struct rlimit lim; 3391d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike int err = getrlimit(RLIMIT_CORE, &lim); 3401d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike 341ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (err) { 3421d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike perror("Getting core dump limit"); 3431d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike return; 3441d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike } 3451d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike 3461d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike printf("Core dump limits :\n\tsoft - "); 347ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (lim.rlim_cur == RLIM_INFINITY) 3481d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike printf("NONE\n"); 3491d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike else printf("%lu\n", lim.rlim_cur); 3501d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike 3511d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike printf("\thard - "); 352ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (lim.rlim_max == RLIM_INFINITY) 3531d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike printf("NONE\n"); 3541d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike else printf("%lu\n", lim.rlim_max); 3551d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike} 3561d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike 35736e454630473caa178bcbc4982ed6a68cf002e95Jeff Dikevoid __init os_early_checks(void) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 359576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike int pid; 360576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike 3611d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike /* Print out the core dump limits early */ 3621d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike check_coredump_limit(); 3631d94cda04eb82feb87c932ac3d4aef1e9dc78a43Jeff Dike 36460d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov check_ptrace(); 3650f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 3660f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike /* Need to check this early because mmapping happens before the 3670f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike * kernel is running. 3680f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike */ 3690f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike check_tmpexec(); 370576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike 371576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike pid = start_ptraced_child(); 372576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike if (init_registers(pid)) 373576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike fatal("Failed to initialize default registers"); 374576c013df0ac9ad1f217452c14ddde246bb1a70dJeff Dike stop_ptraced_child(pid, 1, 1); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 377d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesserstatic int __init noprocmm_cmd_param(char *str, int* add) 378d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser{ 37953c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_proc_mm = 1; 380d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser return 0; 381d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser} 382d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser 383d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser__uml_setup("noprocmm", noprocmm_cmd_param, 384d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser"noprocmm\n" 385d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" Turns off usage of /proc/mm, even if host supports it.\n" 386d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" To support /proc/mm, the host needs to be patched using\n" 387d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" the current skas3 patch.\n\n"); 388d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser 389d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesserstatic int __init noptracefaultinfo_cmd_param(char *str, int* add) 390d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser{ 39153c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_ptrace_faultinfo = 1; 392d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser return 0; 393d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser} 394d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser 395d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser__uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, 396d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser"noptracefaultinfo\n" 397d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" Turns off usage of PTRACE_FAULTINFO, even if host supports\n" 398d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" it. To support PTRACE_FAULTINFO, the host needs to be patched\n" 399d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser" using the current skas3 patch.\n\n"); 400d9838d86536fe17e76d19bf3e737100fae618396Bodo Stroesser 401858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesserstatic int __init noptraceldt_cmd_param(char *str, int* add) 402858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser{ 40353c258787427ea43ebfa76fefa6534cae507e521Jeff Dike disable_ptrace_ldt = 1; 404858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser return 0; 405858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser} 406858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 407858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser__uml_setup("noptraceldt", noptraceldt_cmd_param, 408858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser"noptraceldt\n" 409858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser" Turns off usage of PTRACE_LDT, even if host supports it.\n" 410858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser" To support PTRACE_LDT, the host needs to be patched using\n" 411858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser" the current skas3 patch.\n\n"); 412858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 413858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesserstatic inline void check_skas3_ptrace_faultinfo(void) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ptrace_faultinfo fi; 416d67b569f5f620c0fb95d5212642746b7ba9d29e4Jeff Dike int pid, n; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4183a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal(" - PTRACE_FAULTINFO..."); 4193cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = start_ptraced_child(); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n < 0) { 423ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (errno == EIO) 4243a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("not found\n"); 42560d339f6fe0831060600c62418b71a62ad26c281Gennady Sharapov else 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perror("not found"); 42753c258787427ea43ebfa76fefa6534cae507e521Jeff Dike } else if (disable_ptrace_faultinfo) 42853c258787427ea43ebfa76fefa6534cae507e521Jeff Dike non_fatal("found but disabled on command line\n"); 429d67b569f5f620c0fb95d5212642746b7ba9d29e4Jeff Dike else { 43053c258787427ea43ebfa76fefa6534cae507e521Jeff Dike ptrace_faultinfo = 1; 43153c258787427ea43ebfa76fefa6534cae507e521Jeff Dike non_fatal("found\n"); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4343cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike stop_ptraced_child(pid, 1, 1); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 437858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesserstatic inline void check_skas3_ptrace_ldt(void) 438858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser{ 439858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser#ifdef PTRACE_LDT 440858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser int pid, n; 441858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser unsigned char ldtbuf[40]; 442858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser struct ptrace_ldt ldt_op = (struct ptrace_ldt) { 443858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser .func = 2, /* read default ldt */ 444858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser .ptr = ldtbuf, 445858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser .bytecount = sizeof(ldtbuf)}; 446858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 4473a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal(" - PTRACE_LDT..."); 4483cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike pid = start_ptraced_child(); 449858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 450858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); 451858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser if (n < 0) { 452ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (errno == EIO) 4533a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("not found\n"); 45453c258787427ea43ebfa76fefa6534cae507e521Jeff Dike else 455858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser perror("not found"); 45653c258787427ea43ebfa76fefa6534cae507e521Jeff Dike } else if (disable_ptrace_ldt) 45753c258787427ea43ebfa76fefa6534cae507e521Jeff Dike non_fatal("found, but use is disabled\n"); 458858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser else { 45953c258787427ea43ebfa76fefa6534cae507e521Jeff Dike ptrace_ldt = 1; 46053c258787427ea43ebfa76fefa6534cae507e521Jeff Dike non_fatal("found\n"); 461858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser } 462858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 4633cdaf45578b9aa1eb748d0a32678ee5a0180575bJeff Dike stop_ptraced_child(pid, 1, 1); 464858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser#endif 465858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser} 466858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 467858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesserstatic inline void check_skas3_proc_mm(void) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4693a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal(" - /proc/mm..."); 47053c258787427ea43ebfa76fefa6534cae507e521Jeff Dike if (access("/proc/mm", W_OK) < 0) 4713a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike perror("not found"); 47253c258787427ea43ebfa76fefa6534cae507e521Jeff Dike else if (disable_proc_mm) 473ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike non_fatal("found but disabled on command line\n"); 47453c258787427ea43ebfa76fefa6534cae507e521Jeff Dike else { 47553c258787427ea43ebfa76fefa6534cae507e521Jeff Dike proc_mm = 1; 47653c258787427ea43ebfa76fefa6534cae507e521Jeff Dike non_fatal("found\n"); 47753c258787427ea43ebfa76fefa6534cae507e521Jeff Dike } 478858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser} 479858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 4806b7e967484f4197d799e14b844b78118e93192c6Karol Swietlickivoid can_do_skas(void) 481858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser{ 4823a150e1da8bc4e840d5a09fc089052011b5b6503Jeff Dike non_fatal("Checking for the skas3 patch in the host:\n"); 483858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 484858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser check_skas3_proc_mm(); 485858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser check_skas3_ptrace_faultinfo(); 486858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser check_skas3_ptrace_ldt(); 487858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser 488ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt) 489858259cf7d1c443c836a2022b78cb281f0a9b95eBodo Stroesser skas_needs_stub = 1; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4910f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 4920f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dikeint __init parse_iomem(char *str, int *add) 4930f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike{ 4940f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike struct iomem_region *new; 49573c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike struct stat64 buf; 4960f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike char *file, *driver; 49773c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike int fd, size; 4980f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 4990f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike driver = str; 5000f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike file = strchr(str,','); 501ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (file == NULL) { 502626c59f5edb284027bfe25cc15e7de2f532090b5WANG Cong fprintf(stderr, "parse_iomem : failed to parse iomem\n"); 5030f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike goto out; 5040f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike } 5050f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike *file = '\0'; 5060f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike file++; 50773c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike fd = open(file, O_RDWR, 0); 508ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (fd < 0) { 509512b6fb1c14d4c34f23a3419b0789ad01914a899Jeff Dike perror("parse_iomem - Couldn't open io file"); 5100f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike goto out; 5110f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike } 5120f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 513ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (fstat64(fd, &buf) < 0) { 51473c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike perror("parse_iomem - cannot stat_fd file"); 5150f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike goto out_close; 5160f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike } 5170f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 5180f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike new = malloc(sizeof(*new)); 519ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (new == NULL) { 5200f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike perror("Couldn't allocate iomem_region struct"); 5210f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike goto out_close; 5220f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike } 5230f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 52473c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); 5250f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 5260f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike *new = ((struct iomem_region) { .next = iomem_regions, 5270f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike .driver = driver, 5280f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike .fd = fd, 5290f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike .size = size, 5300f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike .phys = 0, 5310f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike .virt = 0 }); 5320f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike iomem_regions = new; 5330f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike iomem_size += new->size + UM_KERN_PAGE_SIZE; 5340f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike 5359eae9b132cd2cebf98cc45550049d421302b9abaJeff Dike return 0; 5360f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike out_close: 53773c8f4441f07dd3b9d198ec0e97ce83138a6224cJeff Dike close(fd); 5380f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike out: 5399eae9b132cd2cebf98cc45550049d421302b9abaJeff Dike return 1; 5400f80bc85c587e8fdeecece4f294a47eca4922ea2Jeff Dike} 541