blob: f22715868929e9ba0e5f7343c0461e0558661278 [file] [log] [blame]
Gennady Sharapov60d339f62005-09-03 15:57:47 -07001/*
Jeff Dikeba180fd2007-10-16 01:27:00 -07002 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Licensed under the GPL
4 */
5
6#include <stdio.h>
Jeff Dike0f80bc82005-09-16 19:27:50 -07007#include <stdlib.h>
Jeff Dikeba180fd2007-10-16 01:27:00 -07008#include <stdarg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <unistd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <errno.h>
Jeff Dikeba180fd2007-10-16 01:27:00 -070011#include <fcntl.h>
12#include <sched.h>
13#include <signal.h>
14#include <string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <sys/mman.h>
Jeff Dikeba180fd2007-10-16 01:27:00 -070016#include <sys/ptrace.h>
17#include <sys/stat.h>
18#include <sys/wait.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <asm/unistd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "init.h"
Jeff Dike0f80bc82005-09-16 19:27:50 -070021#include "kern_constants.h"
Jeff Dikeba180fd2007-10-16 01:27:00 -070022#include "os.h"
23#include "mem_user.h"
24#include "ptrace_user.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include "registers.h"
Jeff Dikeba180fd2007-10-16 01:27:00 -070026#include "skas_ptrace.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Jeff Dikeb85e9682005-07-28 21:16:01 -070028static int ptrace_child(void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
30 int ret;
31 int pid = os_getpid(), ppid = getppid();
32 int sc_result;
33
Jeff Dike43b00fd2006-02-07 12:58:42 -080034 change_sig(SIGWINCH, 0);
Jeff Dikeba180fd2007-10-16 01:27:00 -070035 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 perror("ptrace");
37 os_kill_process(pid, 0);
38 }
Jeff Dike73c8f4442007-02-10 01:44:20 -080039 kill(pid, SIGSTOP);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Jeff Dikeba180fd2007-10-16 01:27:00 -070041 /*
42 * This syscall will be intercepted by the parent. Don't call more than
43 * once, please.
44 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 sc_result = os_getpid();
46
47 if (sc_result == pid)
Jeff Dikeba180fd2007-10-16 01:27:00 -070048 /* Nothing modified by the parent, we are running normally. */
49 ret = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 else if (sc_result == ppid)
Jeff Dikeba180fd2007-10-16 01:27:00 -070051 /*
52 * Expected in check_ptrace and check_sysemu when they succeed
53 * in modifying the stack frame
54 */
55 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 else
Jeff Dikeba180fd2007-10-16 01:27:00 -070057 /* 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 _exit(ret);
63}
64
Jeff Dike3a150e12007-02-10 01:44:28 -080065static void fatal_perror(char *str)
66{
67 perror(str);
68 exit(1);
69}
70
71static 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
83static 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
Jeff Dikeb85e9682005-07-28 21:16:01 -070093static int start_ptraced_child(void **stack_out)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
Jeff Dikeb85e9682005-07-28 21:16:01 -070095 void *stack;
96 unsigned long sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 int pid, n, status;
Gennady Sharapov60d339f62005-09-03 15:57:47 -070098
Jeff Dikec539ab72007-06-16 10:16:09 -070099 stack = mmap(NULL, UM_KERN_PAGE_SIZE,
100 PROT_READ | PROT_WRITE | PROT_EXEC,
Jeff Dikeb85e9682005-07-28 21:16:01 -0700101 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700102 if (stack == MAP_FAILED)
Jeff Dike3a150e12007-02-10 01:44:28 -0800103 fatal_perror("check_ptrace : mmap failed");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700104
Jeff Dikec539ab72007-06-16 10:16:09 -0700105 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
Jeff Dikeb85e9682005-07-28 21:16:01 -0700106 pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700107 if (pid < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800108 fatal_perror("start_ptraced_child : clone failed");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700111 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800112 fatal_perror("check_ptrace : clone failed");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700113 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
Jeff Dike3a150e12007-02-10 01:44:28 -0800114 fatal("check_ptrace : expected SIGSTOP, got status = %d",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 status);
116
Jeff Dikeb85e9682005-07-28 21:16:01 -0700117 *stack_out = stack;
Jeff Dike9eae9b12007-02-10 01:44:20 -0800118 return pid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
120
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700121/* 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.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * So only for SYSEMU features we test mustpanic, while normal host features
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700125 * must work anyway!
126 */
127static int stop_ptraced_child(int pid, void *stack, int exitcode,
Jeff Dike3a150e12007-02-10 01:44:28 -0800128 int mustexit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 int status, n, ret = 0;
131
Jeff Dikeba180fd2007-10-16 01:27:00 -0700132 if (ptrace(PTRACE_CONT, pid, 0, 0) < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800133 fatal_perror("stop_ptraced_child : ptrace failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 CATCH_EINTR(n = waitpid(pid, &status, 0));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700135 if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 int exit_with = WEXITSTATUS(status);
137 if (exit_with == 2)
Jeff Dike3a150e12007-02-10 01:44:28 -0800138 non_fatal("check_ptrace : child exited with status 2. "
Jeff Dikecf6aced2007-05-23 13:57:40 -0700139 "\nDisabling SYSEMU support.\n");
Jeff Dike3a150e12007-02-10 01:44:28 -0800140 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 ret = -1;
146 }
147
Jeff Dikeba180fd2007-10-16 01:27:00 -0700148 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800149 fatal_perror("check_ptrace : munmap failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 return ret;
151}
152
Jeff Dike7242a402007-02-10 01:44:19 -0800153/* Changed only during early boot */
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700154int ptrace_faultinfo = 1;
Bodo Stroesser858259c2005-11-07 00:58:55 -0800155int ptrace_ldt = 1;
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700156int proc_mm = 1;
Bodo Stroesser858259c2005-11-07 00:58:55 -0800157int skas_needs_stub = 0;
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700158
159static int __init skas0_cmd_param(char *str, int* add)
160{
161 ptrace_faultinfo = proc_mm = 0;
162 return 0;
163}
164
Paolo 'Blaisorblade' Giarrusso9e3d8622005-10-09 21:37:18 +0200165/* The two __uml_setup would conflict, without this stupid alias. */
166
167static int __init mode_skas0_cmd_param(char *str, int* add)
168 __attribute__((alias("skas0_cmd_param")));
169
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700170__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
Paolo 'Blaisorblade' Giarrusso9e3d8622005-10-09 21:37:18 +0200175__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
Jeff Dike7242a402007-02-10 01:44:19 -0800181/* Changed only during early boot */
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700182static int force_sysemu_disabled = 0;
183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184static 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,
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700191"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");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199static void __init check_sysemu(void)
200{
Jeff Dikeb85e9682005-07-28 21:16:01 -0700201 void *stack;
Jeff Dikecf6aced2007-05-23 13:57:40 -0700202 unsigned long regs[MAX_REG_NR];
Jeff Dike9eae9b12007-02-10 01:44:20 -0800203 int pid, n, status, count=0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Jeff Dike3a150e12007-02-10 01:44:28 -0800205 non_fatal("Checking syscall emulation patch for ptrace...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 sysemu_supported = 0;
Jeff Dikeb85e9682005-07-28 21:16:01 -0700207 pid = start_ptraced_child(&stack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Jeff Dikeba180fd2007-10-16 01:27:00 -0700209 if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 goto fail;
211
212 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
213 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800214 fatal_perror("check_sysemu : wait failed");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700215 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
Jeff Dike3a150e12007-02-10 01:44:28 -0800216 fatal("check_sysemu : expected SIGTRAP, got status = %d",
217 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Jeff Dikeba180fd2007-10-16 01:27:00 -0700219 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
Jeff Dikecf6aced2007-05-23 13:57:40 -0700220 fatal_perror("check_sysemu : PTRACE_GETREGS failed");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700221 if (PT_SYSCALL_NR(regs) != __NR_getpid) {
Jeff Dikecf6aced2007-05-23 13:57:40 -0700222 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());
Jeff Dikeba180fd2007-10-16 01:27:00 -0700228 if (n < 0) {
Jeff Dikecf6aced2007-05-23 13:57:40 -0700229 non_fatal("check_sysemu : failed to modify system call "
230 "return");
231 goto fail;
232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Jeff Dikeb85e9682005-07-28 21:16:01 -0700234 if (stop_ptraced_child(pid, stack, 0, 0) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 goto fail_stopped;
236
237 sysemu_supported = 1;
Jeff Dike3a150e12007-02-10 01:44:28 -0800238 non_fatal("OK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 set_using_sysemu(!force_sysemu_disabled);
240
Jeff Dike3a150e12007-02-10 01:44:28 -0800241 non_fatal("Checking advanced syscall emulation patch for ptrace...");
Jeff Dikeb85e9682005-07-28 21:16:01 -0700242 pid = start_ptraced_child(&stack);
Bodo Stroesserf9dfefe2005-09-03 15:57:51 -0700243
Jeff Dikeba180fd2007-10-16 01:27:00 -0700244 if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
Jeff Dike3a150e12007-02-10 01:44:28 -0800245 (void *) PTRACE_O_TRACESYSGOOD) < 0))
246 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
Bodo Stroesserf9dfefe2005-09-03 15:57:51 -0700247
Jeff Dikeba180fd2007-10-16 01:27:00 -0700248 while (1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 count++;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700250 if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 goto fail;
252 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700253 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800254 fatal_perror("check_ptrace : wait failed");
255
Jeff Dikeba180fd2007-10-16 01:27:00 -0700256 if (WIFSTOPPED(status) &&
257 (WSTOPSIG(status) == (SIGTRAP|0x80))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 if (!count)
Jeff Dike3a150e12007-02-10 01:44:28 -0800259 fatal("check_ptrace : SYSEMU_SINGLESTEP "
Bodo Stroesserf9dfefe2005-09-03 15:57:51 -0700260 "doesn't singlestep");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
262 os_getpid());
Jeff Dikeba180fd2007-10-16 01:27:00 -0700263 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800264 fatal_perror("check_sysemu : failed to modify "
265 "system call return");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 break;
267 }
Jeff Dikeba180fd2007-10-16 01:27:00 -0700268 else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
Bodo Stroesserf9dfefe2005-09-03 15:57:51 -0700269 count++;
270 else
Jeff Dike3a150e12007-02-10 01:44:28 -0800271 fatal("check_ptrace : expected SIGTRAP or "
272 "(SIGTRAP | 0x80), got status = %d", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
Jeff Dikeb85e9682005-07-28 21:16:01 -0700274 if (stop_ptraced_child(pid, stack, 0, 0) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 goto fail_stopped;
276
277 sysemu_supported = 2;
Jeff Dike3a150e12007-02-10 01:44:28 -0800278 non_fatal("OK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Jeff Dikeba180fd2007-10-16 01:27:00 -0700280 if (!force_sysemu_disabled)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 set_using_sysemu(sysemu_supported);
282 return;
283
284fail:
Jeff Dikeb85e9682005-07-28 21:16:01 -0700285 stop_ptraced_child(pid, stack, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286fail_stopped:
Jeff Dike3a150e12007-02-10 01:44:28 -0800287 non_fatal("missing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700290static void __init check_ptrace(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291{
Jeff Dikeb85e9682005-07-28 21:16:01 -0700292 void *stack;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 int pid, syscall, n, status;
294
Jeff Dike3a150e12007-02-10 01:44:28 -0800295 non_fatal("Checking that ptrace can change system call numbers...");
Jeff Dikeb85e9682005-07-28 21:16:01 -0700296 pid = start_ptraced_child(&stack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Jeff Dikeba180fd2007-10-16 01:27:00 -0700298 if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
Jeff Dike3a150e12007-02-10 01:44:28 -0800299 (void *) PTRACE_O_TRACESYSGOOD) < 0))
300 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Jeff Dikeba180fd2007-10-16 01:27:00 -0700302 while (1) {
303 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800304 fatal_perror("check_ptrace : ptrace failed");
305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700307 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800308 fatal_perror("check_ptrace : wait failed");
309
Jeff Dikeba180fd2007-10-16 01:27:00 -0700310 if (!WIFSTOPPED(status) ||
Jeff Dike3a150e12007-02-10 01:44:28 -0800311 (WSTOPSIG(status) != (SIGTRAP | 0x80)))
312 fatal("check_ptrace : expected (SIGTRAP|0x80), "
313 "got status = %d", status);
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
316 0);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700317 if (syscall == __NR_getpid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
319 __NR_getppid);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700320 if (n < 0)
Jeff Dike3a150e12007-02-10 01:44:28 -0800321 fatal_perror("check_ptrace : failed to modify "
322 "system call");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 break;
324 }
325 }
Jeff Dikeb85e9682005-07-28 21:16:01 -0700326 stop_ptraced_child(pid, stack, 0, 1);
Jeff Dike3a150e12007-02-10 01:44:28 -0800327 non_fatal("OK\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 check_sysemu();
329}
330
Rob Landley966a082f2006-04-18 22:21:43 -0700331extern void check_tmpexec(void);
Jeff Dike0f80bc82005-09-16 19:27:50 -0700332
Jeff Dike36e45462007-05-06 14:51:11 -0700333static void __init check_coredump_limit(void)
Jeff Dike1d94cda2007-05-06 14:51:00 -0700334{
335 struct rlimit lim;
336 int err = getrlimit(RLIMIT_CORE, &lim);
337
Jeff Dikeba180fd2007-10-16 01:27:00 -0700338 if (err) {
Jeff Dike1d94cda2007-05-06 14:51:00 -0700339 perror("Getting core dump limit");
340 return;
341 }
342
343 printf("Core dump limits :\n\tsoft - ");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700344 if (lim.rlim_cur == RLIM_INFINITY)
Jeff Dike1d94cda2007-05-06 14:51:00 -0700345 printf("NONE\n");
346 else printf("%lu\n", lim.rlim_cur);
347
348 printf("\thard - ");
Jeff Dikeba180fd2007-10-16 01:27:00 -0700349 if (lim.rlim_max == RLIM_INFINITY)
Jeff Dike1d94cda2007-05-06 14:51:00 -0700350 printf("NONE\n");
351 else printf("%lu\n", lim.rlim_max);
352}
353
Jeff Dike36e45462007-05-06 14:51:11 -0700354void __init os_early_checks(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355{
Jeff Dike1d94cda2007-05-06 14:51:00 -0700356 /* Print out the core dump limits early */
357 check_coredump_limit();
358
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700359 check_ptrace();
Jeff Dike0f80bc82005-09-16 19:27:50 -0700360
361 /* Need to check this early because mmapping happens before the
362 * kernel is running.
363 */
364 check_tmpexec();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365}
366
Bodo Stroesserd9838d82005-09-03 15:57:51 -0700367static 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
379static 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
Bodo Stroesser858259c2005-11-07 00:58:55 -0800391static 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
Bodo Stroesser858259c2005-11-07 00:58:55 -0800403static inline void check_skas3_ptrace_faultinfo(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
405 struct ptrace_faultinfo fi;
Jeff Dikeb85e9682005-07-28 21:16:01 -0700406 void *stack;
Jeff Diked67b5692005-07-07 17:56:49 -0700407 int pid, n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Jeff Dike3a150e12007-02-10 01:44:28 -0800409 non_fatal(" - PTRACE_FAULTINFO...");
Jeff Dikeb85e9682005-07-28 21:16:01 -0700410 pid = start_ptraced_child(&stack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
412 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
413 if (n < 0) {
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700414 ptrace_faultinfo = 0;
Jeff Dikeba180fd2007-10-16 01:27:00 -0700415 if (errno == EIO)
Jeff Dike3a150e12007-02-10 01:44:28 -0800416 non_fatal("not found\n");
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700417 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 perror("not found");
Jeff Diked67b5692005-07-07 17:56:49 -0700419 }
420 else {
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700421 if (!ptrace_faultinfo)
Jeff Dike3a150e12007-02-10 01:44:28 -0800422 non_fatal("found but disabled on command line\n");
Paolo 'Blaisorblade' Giarrussocb665042005-07-27 11:43:31 -0700423 else
Jeff Dike3a150e12007-02-10 01:44:28 -0800424 non_fatal("found\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 }
426
427 init_registers(pid);
Jeff Dikeb85e9682005-07-28 21:16:01 -0700428 stop_ptraced_child(pid, stack, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Bodo Stroesser858259c2005-11-07 00:58:55 -0800431static inline void check_skas3_ptrace_ldt(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
Bodo Stroesser858259c2005-11-07 00:58:55 -0800433#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
Jeff Dike3a150e12007-02-10 01:44:28 -0800442 non_fatal(" - PTRACE_LDT...");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800443 pid = start_ptraced_child(&stack);
444
445 n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
446 if (n < 0) {
Jeff Dikeba180fd2007-10-16 01:27:00 -0700447 if (errno == EIO)
Jeff Dike3a150e12007-02-10 01:44:28 -0800448 non_fatal("not found\n");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800449 else {
450 perror("not found");
451 }
452 ptrace_ldt = 0;
453 }
454 else {
Jeff Dikeba180fd2007-10-16 01:27:00 -0700455 if (ptrace_ldt)
Jeff Dike3a150e12007-02-10 01:44:28 -0800456 non_fatal("found\n");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800457 else
Jeff Dike3a150e12007-02-10 01:44:28 -0800458 non_fatal("found, but use is disabled\n");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800459 }
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
471static inline void check_skas3_proc_mm(void)
472{
Jeff Dike3a150e12007-02-10 01:44:28 -0800473 non_fatal(" - /proc/mm...");
Jeff Dike73c8f4442007-02-10 01:44:20 -0800474 if (access("/proc/mm", W_OK) < 0) {
Jeff Dike9eae9b12007-02-10 01:44:20 -0800475 proc_mm = 0;
Jeff Dike3a150e12007-02-10 01:44:28 -0800476 perror("not found");
Gennady Sharapov60d339f62005-09-03 15:57:47 -0700477 }
Jeff Dikeba180fd2007-10-16 01:27:00 -0700478 else if (!proc_mm)
479 non_fatal("found but disabled on command line\n");
480 else non_fatal("found\n");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800481}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Bodo Stroesser858259c2005-11-07 00:58:55 -0800483int can_do_skas(void)
484{
Jeff Dike3a150e12007-02-10 01:44:28 -0800485 non_fatal("Checking for the skas3 patch in the host:\n");
Bodo Stroesser858259c2005-11-07 00:58:55 -0800486
487 check_skas3_proc_mm();
488 check_skas3_ptrace_faultinfo();
489 check_skas3_ptrace_ldt();
490
Jeff Dikeba180fd2007-10-16 01:27:00 -0700491 if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
Bodo Stroesser858259c2005-11-07 00:58:55 -0800492 skas_needs_stub = 1;
493
Jeff Diked67b5692005-07-07 17:56:49 -0700494 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495}
Jeff Dike0f80bc82005-09-16 19:27:50 -0700496
Jeff Dike0f80bc82005-09-16 19:27:50 -0700497int __init parse_iomem(char *str, int *add)
498{
499 struct iomem_region *new;
Jeff Dike73c8f4442007-02-10 01:44:20 -0800500 struct stat64 buf;
Jeff Dike0f80bc82005-09-16 19:27:50 -0700501 char *file, *driver;
Jeff Dike73c8f4442007-02-10 01:44:20 -0800502 int fd, size;
Jeff Dike0f80bc82005-09-16 19:27:50 -0700503
504 driver = str;
505 file = strchr(str,',');
Jeff Dikeba180fd2007-10-16 01:27:00 -0700506 if (file == NULL) {
Jeff Dike0f80bc82005-09-16 19:27:50 -0700507 printf("parse_iomem : failed to parse iomem\n");
508 goto out;
509 }
510 *file = '\0';
511 file++;
Jeff Dike73c8f4442007-02-10 01:44:20 -0800512 fd = open(file, O_RDWR, 0);
Jeff Dikeba180fd2007-10-16 01:27:00 -0700513 if (fd < 0) {
Jeff Dike0f80bc82005-09-16 19:27:50 -0700514 os_print_error(fd, "parse_iomem - Couldn't open io file");
515 goto out;
516 }
517
Jeff Dikeba180fd2007-10-16 01:27:00 -0700518 if (fstat64(fd, &buf) < 0) {
Jeff Dike73c8f4442007-02-10 01:44:20 -0800519 perror("parse_iomem - cannot stat_fd file");
Jeff Dike0f80bc82005-09-16 19:27:50 -0700520 goto out_close;
521 }
522
523 new = malloc(sizeof(*new));
Jeff Dikeba180fd2007-10-16 01:27:00 -0700524 if (new == NULL) {
Jeff Dike0f80bc82005-09-16 19:27:50 -0700525 perror("Couldn't allocate iomem_region struct");
526 goto out_close;
527 }
528
Jeff Dike73c8f4442007-02-10 01:44:20 -0800529 size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
Jeff Dike0f80bc82005-09-16 19:27:50 -0700530
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
Jeff Dike9eae9b12007-02-10 01:44:20 -0800540 return 0;
Jeff Dike0f80bc82005-09-16 19:27:50 -0700541 out_close:
Jeff Dike73c8f4442007-02-10 01:44:20 -0800542 close(fd);
Jeff Dike0f80bc82005-09-16 19:27:50 -0700543 out:
Jeff Dike9eae9b12007-02-10 01:44:20 -0800544 return 1;
Jeff Dike0f80bc82005-09-16 19:27:50 -0700545}