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