aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/include/kern_util.h1
-rw-r--r--arch/um/include/os.h8
-rw-r--r--arch/um/include/registers.h6
-rw-r--r--arch/um/kernel/skas/mmu.c5
-rw-r--r--arch/um/kernel/skas/process.c20
-rw-r--r--arch/um/kernel/trap.c12
-rw-r--r--arch/um/os-Linux/registers.c21
-rw-r--r--arch/um/os-Linux/skas/process.c265
-rw-r--r--arch/um/os-Linux/start_up.c4
-rw-r--r--arch/um/sys-x86_64/syscalls.c8
10 files changed, 233 insertions, 117 deletions
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 8fadf8962e3e..625ca2924a56 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -62,6 +62,7 @@ extern int singlestepping(void *t);
62extern void segv_handler(int sig, struct uml_pt_regs *regs); 62extern void segv_handler(int sig, struct uml_pt_regs *regs);
63extern void bus_handler(int sig, struct uml_pt_regs *regs); 63extern void bus_handler(int sig, struct uml_pt_regs *regs);
64extern void winch(int sig, struct uml_pt_regs *regs); 64extern void winch(int sig, struct uml_pt_regs *regs);
65extern void fatal_sigsegv(void) __attribute__ ((noreturn));
65 66
66 67
67#endif 68#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 69c0d4ad0e52..9428d34792ca 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -238,7 +238,7 @@ extern int raw(int fd);
238extern void setup_machinename(char *machine_out); 238extern void setup_machinename(char *machine_out);
239extern void setup_hostinfo(char *buf, int len); 239extern void setup_hostinfo(char *buf, int len);
240extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 240extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
241extern void os_dump_core(void); 241extern void os_dump_core(void) __attribute__ ((noreturn));
242 242
243/* time.c */ 243/* time.c */
244extern void idle_sleep(unsigned long long nsecs); 244extern void idle_sleep(unsigned long long nsecs);
@@ -267,11 +267,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
267extern int is_skas_winch(int pid, int fd, void *data); 267extern int is_skas_winch(int pid, int fd, void *data);
268extern int start_userspace(unsigned long stub_stack); 268extern int start_userspace(unsigned long stub_stack);
269extern int copy_context_skas0(unsigned long stack, int pid); 269extern int copy_context_skas0(unsigned long stack, int pid);
270extern void save_registers(int pid, struct uml_pt_regs *regs);
271extern void restore_registers(int pid, struct uml_pt_regs *regs);
272extern void userspace(struct uml_pt_regs *regs); 270extern void userspace(struct uml_pt_regs *regs);
273extern void map_stub_pages(int fd, unsigned long code, 271extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
274 unsigned long data, unsigned long stack); 272 unsigned long stack);
275extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); 273extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
276extern void switch_threads(jmp_buf *me, jmp_buf *you); 274extern void switch_threads(jmp_buf *me, jmp_buf *you);
277extern int start_idle_thread(void *stack, jmp_buf *switch_buf); 275extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 6df37480cb8c..9ea1ae3c8f46 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -13,9 +13,9 @@ extern int save_fp_registers(int pid, unsigned long *fp_regs);
13extern int restore_fp_registers(int pid, unsigned long *fp_regs); 13extern int restore_fp_registers(int pid, unsigned long *fp_regs);
14extern int save_fpx_registers(int pid, unsigned long *fp_regs); 14extern int save_fpx_registers(int pid, unsigned long *fp_regs);
15extern int restore_fpx_registers(int pid, unsigned long *fp_regs); 15extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
16extern void save_registers(int pid, struct uml_pt_regs *regs); 16extern int save_registers(int pid, struct uml_pt_regs *regs);
17extern void restore_registers(int pid, struct uml_pt_regs *regs); 17extern int restore_registers(int pid, struct uml_pt_regs *regs);
18extern void init_registers(int pid); 18extern int init_registers(int pid);
19extern void get_safe_registers(unsigned long *regs); 19extern void get_safe_registers(unsigned long *regs);
20extern unsigned long get_thread_reg(int reg, jmp_buf *buf); 20extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
21 21
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index b56fe8b67a81..6da9ab4f5a18 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -114,6 +114,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
114 to_mm->id.u.pid = copy_context_skas0(stack, 114 to_mm->id.u.pid = copy_context_skas0(stack,
115 from_mm->id.u.pid); 115 from_mm->id.u.pid);
116 else to_mm->id.u.pid = start_userspace(stack); 116 else to_mm->id.u.pid = start_userspace(stack);
117
118 if (to_mm->id.u.pid < 0) {
119 ret = to_mm->id.u.pid;
120 goto out_free;
121 }
117 } 122 }
118 123
119 ret = init_new_ldt(to_mm, from_mm); 124 ret = init_new_ldt(to_mm, from_mm);
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index fce389c2342f..2e9852c0d487 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -6,19 +6,25 @@
6#include "linux/init.h" 6#include "linux/init.h"
7#include "linux/sched.h" 7#include "linux/sched.h"
8#include "as-layout.h" 8#include "as-layout.h"
9#include "kern.h"
9#include "os.h" 10#include "os.h"
10#include "skas.h" 11#include "skas.h"
11 12
12int new_mm(unsigned long stack) 13int new_mm(unsigned long stack)
13{ 14{
14 int fd; 15 int fd, err;
15 16
16 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); 17 fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
17 if (fd < 0) 18 if (fd < 0)
18 return fd; 19 return fd;
19 20
20 if (skas_needs_stub) 21 if (skas_needs_stub) {
21 map_stub_pages(fd, STUB_CODE, STUB_DATA, stack); 22 err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
23 if (err) {
24 os_close_file(fd);
25 return err;
26 }
27 }
22 28
23 return fd; 29 return fd;
24} 30}
@@ -49,8 +55,14 @@ int __init start_uml(void)
49{ 55{
50 stack_protections((unsigned long) &cpu0_irqstack); 56 stack_protections((unsigned long) &cpu0_irqstack);
51 set_sigstack(cpu0_irqstack, THREAD_SIZE); 57 set_sigstack(cpu0_irqstack, THREAD_SIZE);
52 if (proc_mm) 58 if (proc_mm) {
53 userspace_pid[0] = start_userspace(0); 59 userspace_pid[0] = start_userspace(0);
60 if (userspace_pid[0] < 0) {
61 printf("start_uml - start_userspace returned %d\n",
62 userspace_pid[0]);
63 exit(1);
64 }
65 }
54 66
55 init_new_thread_signals(); 67 init_new_thread_signals();
56 68
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 8fd1a797c3eb..44e490419495 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -129,6 +129,18 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
129 force_sig_info(SIGSEGV, &si, current); 129 force_sig_info(SIGSEGV, &si, current);
130} 130}
131 131
132void fatal_sigsegv(void)
133{
134 force_sigsegv(SIGSEGV, current);
135 do_signal();
136 /*
137 * This is to tell gcc that we're not returning - do_signal
138 * can, in general, return, but in this case, it's not, since
139 * we just got a fatal SIGSEGV queued.
140 */
141 os_dump_core();
142}
143
132void segv_handler(int sig, struct uml_pt_regs *regs) 144void segv_handler(int sig, struct uml_pt_regs *regs)
133{ 145{
134 struct faultinfo * fi = UPT_FAULTINFO(regs); 146 struct faultinfo * fi = UPT_FAULTINFO(regs);
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index c78fae3aba81..830fe6a1518a 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -8,42 +8,41 @@
8#include <string.h> 8#include <string.h>
9#include <sys/ptrace.h> 9#include <sys/ptrace.h>
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11#include "user.h"
12 11
13void save_registers(int pid, struct uml_pt_regs *regs) 12int save_registers(int pid, struct uml_pt_regs *regs)
14{ 13{
15 int err; 14 int err;
16 15
17 err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp); 16 err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
18 if (err < 0) 17 if (err < 0)
19 panic("save_registers - saving registers failed, errno = %d\n", 18 return -errno;
20 errno); 19 return 0;
21} 20}
22 21
23void restore_registers(int pid, struct uml_pt_regs *regs) 22int restore_registers(int pid, struct uml_pt_regs *regs)
24{ 23{
25 int err; 24 int err;
26 25
27 err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp); 26 err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
28 if (err < 0) 27 if (err < 0)
29 panic("restore_registers - saving registers failed, " 28 return -errno;
30 "errno = %d\n", errno); 29 return 0;
31} 30}
32 31
33/* This is set once at boot time and not changed thereafter */ 32/* This is set once at boot time and not changed thereafter */
34 33
35static unsigned long exec_regs[MAX_REG_NR]; 34static unsigned long exec_regs[MAX_REG_NR];
36 35
37void init_registers(int pid) 36int init_registers(int pid)
38{ 37{
39 int err; 38 int err;
40 39
41 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs); 40 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
42 if (err) 41 if (err < 0)
43 panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", 42 return -errno;
44 errno);
45 43
46 arch_init_registers(pid); 44 arch_init_registers(pid);
45 return 0;
47} 46}
48 47
49void get_safe_registers(unsigned long *regs) 48void get_safe_registers(unsigned long *regs)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 7dc24e3cb190..862fea0290ec 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -38,17 +38,17 @@ int is_skas_winch(int pid, int fd, void *data)
38 38
39static int ptrace_dump_regs(int pid) 39static int ptrace_dump_regs(int pid)
40{ 40{
41 unsigned long regs[MAX_REG_NR]; 41 unsigned long regs[MAX_REG_NR];
42 int i; 42 int i;
43 43
44 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 44 if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
45 return -errno; 45 return -errno;
46 46
47 printk(UM_KERN_ERR "Stub registers -\n"); 47 printk(UM_KERN_ERR "Stub registers -\n");
48 for (i = 0; i < ARRAY_SIZE(regs); i++) 48 for (i = 0; i < ARRAY_SIZE(regs); i++)
49 printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]); 49 printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
50 50
51 return 0; 51 return 0;
52} 52}
53 53
54/* 54/*
@@ -73,9 +73,11 @@ void wait_stub_done(int pid)
73 break; 73 break;
74 74
75 err = ptrace(PTRACE_CONT, pid, 0, 0); 75 err = ptrace(PTRACE_CONT, pid, 0, 0);
76 if (err) 76 if (err) {
77 panic("wait_stub_done : continue failed, errno = %d\n", 77 printk(UM_KERN_ERR "wait_stub_done : continue failed, "
78 errno); 78 "errno = %d\n", errno);
79 fatal_sigsegv();
80 }
79 } 81 }
80 82
81 if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) 83 if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
@@ -86,8 +88,10 @@ bad_wait:
86 if (err) 88 if (err)
87 printk(UM_KERN_ERR "Failed to get registers from stub, " 89 printk(UM_KERN_ERR "Failed to get registers from stub, "
88 "errno = %d\n", -err); 90 "errno = %d\n", -err);
89 panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, " 91 printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
90 "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); 92 "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
93 status);
94 fatal_sigsegv();
91} 95}
92 96
93extern unsigned long current_stub_stack(void); 97extern unsigned long current_stub_stack(void);
@@ -98,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
98 102
99 if (ptrace_faultinfo) { 103 if (ptrace_faultinfo) {
100 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); 104 err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
101 if (err) 105 if (err) {
102 panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " 106 printk(UM_KERN_ERR "get_skas_faultinfo - "
103 "errno = %d\n", errno); 107 "PTRACE_FAULTINFO failed, errno = %d\n", errno);
108 fatal_sigsegv();
109 }
104 110
105 /* Special handling for i386, which has different structs */ 111 /* Special handling for i386, which has different structs */
106 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) 112 if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
@@ -110,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
110 } 116 }
111 else { 117 else {
112 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); 118 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
113 if (err) 119 if (err) {
114 panic("Failed to continue stub, pid = %d, errno = %d\n", 120 printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
115 pid, errno); 121 "errno = %d\n", pid, errno);
122 fatal_sigsegv();
123 }
116 wait_stub_done(pid); 124 wait_stub_done(pid);
117 125
118 /* 126 /*
@@ -145,25 +153,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
145 { 153 {
146 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, 154 err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
147 __NR_getpid); 155 __NR_getpid);
148 if (err < 0) 156 if (err < 0) {
149 panic("handle_trap - nullifying syscall failed, " 157 printk(UM_KERN_ERR "handle_trap - nullifying syscall "
150 "errno = %d\n", errno); 158 "failed, errno = %d\n", errno);
159 fatal_sigsegv();
160 }
151 161
152 err = ptrace(PTRACE_SYSCALL, pid, 0, 0); 162 err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
153 if (err < 0) 163 if (err < 0) {
154 panic("handle_trap - continuing to end of syscall " 164 printk(UM_KERN_ERR "handle_trap - continuing to end of "
155 "failed, errno = %d\n", errno); 165 "syscall failed, errno = %d\n", errno);
166 fatal_sigsegv();
167 }
156 168
157 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); 169 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
158 if ((err < 0) || !WIFSTOPPED(status) || 170 if ((err < 0) || !WIFSTOPPED(status) ||
159 (WSTOPSIG(status) != SIGTRAP + 0x80)) { 171 (WSTOPSIG(status) != SIGTRAP + 0x80)) {
160 err = ptrace_dump_regs(pid); 172 err = ptrace_dump_regs(pid);
161 if (err) 173 if (err)
162 printk(UM_KERN_ERR "Failed to get registers " 174 printk(UM_KERN_ERR "Failed to get registers "
163 "from process, errno = %d\n", -err); 175 "from process, errno = %d\n", -err);
164 panic("handle_trap - failed to wait at end of syscall, " 176 printk(UM_KERN_ERR "handle_trap - failed to wait at "
165 "errno = %d, status = %d\n", errno, status); 177 "end of syscall, errno = %d, status = %d\n",
166 } 178 errno, status);
179 fatal_sigsegv();
180 }
167 } 181 }
168 182
169 handle_syscall(regs); 183 handle_syscall(regs);
@@ -181,9 +195,11 @@ static int userspace_tramp(void *stack)
181 signal(SIGTERM, SIG_DFL); 195 signal(SIGTERM, SIG_DFL);
182 signal(SIGWINCH, SIG_IGN); 196 signal(SIGWINCH, SIG_IGN);
183 err = set_interval(); 197 err = set_interval();
184 if (err) 198 if (err) {
185 panic("userspace_tramp - setting timer failed, errno = %d\n", 199 printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
186 err); 200 "errno = %d\n", err);
201 exit(1);
202 }
187 203
188 if (!proc_mm) { 204 if (!proc_mm) {
189 /* 205 /*
@@ -226,9 +242,11 @@ static int userspace_tramp(void *stack)
226 sa.sa_flags = SA_ONSTACK | SA_NODEFER; 242 sa.sa_flags = SA_ONSTACK | SA_NODEFER;
227 sa.sa_handler = (void *) v; 243 sa.sa_handler = (void *) v;
228 sa.sa_restorer = NULL; 244 sa.sa_restorer = NULL;
229 if (sigaction(SIGSEGV, &sa, NULL) < 0) 245 if (sigaction(SIGSEGV, &sa, NULL) < 0) {
230 panic("userspace_tramp - setting SIGSEGV handler " 246 printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
231 "failed - errno = %d\n", errno); 247 "handler failed - errno = %d\n", errno);
248 exit(1);
249 }
232 } 250 }
233 251
234 kill(os_getpid(), SIGSTOP); 252 kill(os_getpid(), SIGSTOP);
@@ -244,13 +262,18 @@ int start_userspace(unsigned long stub_stack)
244{ 262{
245 void *stack; 263 void *stack;
246 unsigned long sp; 264 unsigned long sp;
247 int pid, status, n, flags; 265 int pid, status, n, flags, err;
248 266
249 stack = mmap(NULL, UM_KERN_PAGE_SIZE, 267 stack = mmap(NULL, UM_KERN_PAGE_SIZE,
250 PROT_READ | PROT_WRITE | PROT_EXEC, 268 PROT_READ | PROT_WRITE | PROT_EXEC,
251 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 269 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
252 if (stack == MAP_FAILED) 270 if (stack == MAP_FAILED) {
253 panic("start_userspace : mmap failed, errno = %d", errno); 271 err = -errno;
272 printk(UM_KERN_ERR "start_userspace : mmap failed, "
273 "errno = %d", errno);
274 return err;
275 }
276
254 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); 277 sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
255 278
256 flags = CLONE_FILES; 279 flags = CLONE_FILES;
@@ -260,29 +283,50 @@ int start_userspace(unsigned long stub_stack)
260 flags |= SIGCHLD; 283 flags |= SIGCHLD;
261 284
262 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); 285 pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
263 if (pid < 0) 286 if (pid < 0) {
264 panic("start_userspace : clone failed, errno = %d", errno); 287 err = -errno;
288 printk(UM_KERN_ERR "start_userspace : clone failed, "
289 "errno = %d", errno);
290 return err;
291 }
265 292
266 do { 293 do {
267 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); 294 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
268 if (n < 0) 295 if (n < 0) {
269 panic("start_userspace : wait failed, errno = %d", 296 err = -errno;
270 errno); 297 printk(UM_KERN_ERR "start_userspace : wait failed, "
298 "errno = %d", errno);
299 goto out_kill;
300 }
271 } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); 301 } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
272 302
273 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 303 if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
274 panic("start_userspace : expected SIGSTOP, got status = %d", 304 err = -EINVAL;
275 status); 305 printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
306 "status = %d", status);
307 goto out_kill;
308 }
276 309
277 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, 310 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
278 (void *) PTRACE_O_TRACESYSGOOD) < 0) 311 (void *) PTRACE_O_TRACESYSGOOD) < 0) {
279 panic("start_userspace : PTRACE_OLDSETOPTIONS failed, " 312 err = -errno;
280 "errno = %d\n", errno); 313 printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
314 "failed, errno = %d\n", errno);
315 goto out_kill;
316 }
281 317
282 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) 318 if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
283 panic("start_userspace : munmap failed, errno = %d\n", errno); 319 err = -errno;
320 printk(UM_KERN_ERR "start_userspace : munmap failed, "
321 "errno = %d\n", errno);
322 goto out_kill;
323 }
284 324
285 return pid; 325 return pid;
326
327 out_kill:
328 os_kill_ptraced_process(pid, 1);
329 return err;
286} 330}
287 331
288void userspace(struct uml_pt_regs *regs) 332void userspace(struct uml_pt_regs *regs)
@@ -300,9 +344,16 @@ void userspace(struct uml_pt_regs *regs)
300 nsecs += os_nsecs(); 344 nsecs += os_nsecs();
301 345
302 while (1) { 346 while (1) {
347 /*
348 * This can legitimately fail if the process loads a
349 * bogus value into a segment register. It will
350 * segfault and PTRACE_GETREGS will read that value
351 * out of the process. However, PTRACE_SETREGS will
352 * fail. In this case, there is nothing to do but
353 * just kill the process.
354 */
303 if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) 355 if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
304 panic("userspace - PTRACE_SETREGS failed, " 356 fatal_sigsegv();
305 "errno = %d\n", errno);
306 357
307 /* Now we set local_using_sysemu to be used for one loop */ 358 /* Now we set local_using_sysemu to be used for one loop */
308 local_using_sysemu = get_using_sysemu(); 359 local_using_sysemu = get_using_sysemu();
@@ -310,21 +361,25 @@ void userspace(struct uml_pt_regs *regs)
310 op = SELECT_PTRACE_OPERATION(local_using_sysemu, 361 op = SELECT_PTRACE_OPERATION(local_using_sysemu,
311 singlestepping(NULL)); 362 singlestepping(NULL));
312 363
313 err = ptrace(op, pid, 0, 0); 364 if (ptrace(op, pid, 0, 0)) {
314 if (err) 365 printk(UM_KERN_ERR "userspace - ptrace continue "
315 panic("userspace - could not resume userspace process, " 366 "failed, op = %d, errno = %d\n", op, errno);
316 "pid=%d, ptrace operation = %d, errno = %d\n", 367 fatal_sigsegv();
317 pid, op, errno); 368 }
318 369
319 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); 370 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
320 if (err < 0) 371 if (err < 0) {
321 panic("userspace - waitpid failed, errno = %d\n", 372 printk(UM_KERN_ERR "userspace - wait failed, "
322 errno); 373 "errno = %d\n", errno);
374 fatal_sigsegv();
375 }
323 376
324 regs->is_user = 1; 377 regs->is_user = 1;
325 if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) 378 if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
326 panic("userspace - saving registers failed, " 379 printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
327 "errno = %d\n", errno); 380 "errno = %d\n", errno);
381 fatal_sigsegv();
382 }
328 383
329 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 384 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
330 385
@@ -371,6 +426,7 @@ void userspace(struct uml_pt_regs *regs)
371 default: 426 default:
372 printk(UM_KERN_ERR "userspace - child stopped " 427 printk(UM_KERN_ERR "userspace - child stopped "
373 "with signal %d\n", sig); 428 "with signal %d\n", sig);
429 fatal_sigsegv();
374 } 430 }
375 pid = userspace_pid[0]; 431 pid = userspace_pid[0];
376 interrupt_end(); 432 interrupt_end();
@@ -422,9 +478,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
422 .it_interval = tv }) }); 478 .it_interval = tv }) });
423 479
424 err = ptrace_setregs(pid, thread_regs); 480 err = ptrace_setregs(pid, thread_regs);
425 if (err < 0) 481 if (err < 0) {
426 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 482 err = -errno;
427 "pid = %d, errno = %d\n", pid, -err); 483 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
484 "failed, pid = %d, errno = %d\n", pid, -err);
485 return err;
486 }
428 487
429 /* set a well known return code for detection of child write failure */ 488 /* set a well known return code for detection of child write failure */
430 child_data->err = 12345678; 489 child_data->err = 12345678;
@@ -434,31 +493,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
434 * parent's stack, and check, if bad result. 493 * parent's stack, and check, if bad result.
435 */ 494 */
436 err = ptrace(PTRACE_CONT, pid, 0, 0); 495 err = ptrace(PTRACE_CONT, pid, 0, 0);
437 if (err) 496 if (err) {
438 panic("Failed to continue new process, pid = %d, " 497 err = -errno;
439 "errno = %d\n", pid, errno); 498 printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
499 "errno = %d\n", pid, errno);
500 return err;
501 }
502
440 wait_stub_done(pid); 503 wait_stub_done(pid);
441 504
442 pid = data->err; 505 pid = data->err;
443 if (pid < 0) 506 if (pid < 0) {
444 panic("copy_context_skas0 - stub-parent reports error %d\n", 507 printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
445 -pid); 508 "error %d\n", -pid);
509 return pid;
510 }
446 511
447 /* 512 /*
448 * Wait, until child has finished too: read child's result from 513 * Wait, until child has finished too: read child's result from
449 * child's stack and check it. 514 * child's stack and check it.
450 */ 515 */
451 wait_stub_done(pid); 516 wait_stub_done(pid);
452 if (child_data->err != STUB_DATA) 517 if (child_data->err != STUB_DATA) {
453 panic("copy_context_skas0 - stub-child reports error %ld\n", 518 printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
454 child_data->err); 519 "error %ld\n", child_data->err);
520 err = child_data->err;
521 goto out_kill;
522 }
455 523
456 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, 524 if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
457 (void *)PTRACE_O_TRACESYSGOOD) < 0) 525 (void *)PTRACE_O_TRACESYSGOOD) < 0) {
458 panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " 526 err = -errno;
459 "errno = %d\n", errno); 527 printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
528 "failed, errno = %d\n", errno);
529 goto out_kill;
530 }
460 531
461 return pid; 532 return pid;
533
534 out_kill:
535 os_kill_ptraced_process(pid, 1);
536 return err;
462} 537}
463 538
464/* 539/*
@@ -466,8 +541,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
466 * available. Opening /proc/mm creates a new mm_context, which lacks 541 * available. Opening /proc/mm creates a new mm_context, which lacks
467 * the stub-pages. Thus, we map them using /proc/mm-fd 542 * the stub-pages. Thus, we map them using /proc/mm-fd
468 */ 543 */
469void map_stub_pages(int fd, unsigned long code, 544int map_stub_pages(int fd, unsigned long code, unsigned long data,
470 unsigned long data, unsigned long stack) 545 unsigned long stack)
471{ 546{
472 struct proc_mm_op mmop; 547 struct proc_mm_op mmop;
473 int n; 548 int n;
@@ -491,8 +566,9 @@ void map_stub_pages(int fd, unsigned long code,
491 printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " 566 printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
492 "offset = %llx\n", code, code_fd, 567 "offset = %llx\n", code, code_fd,
493 (unsigned long long) code_offset); 568 (unsigned long long) code_offset);
494 panic("map_stub_pages : /proc/mm map for code failed, " 569 printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
495 "err = %d\n", n); 570 "failed, err = %d\n", n);
571 return -n;
496 } 572 }
497 573
498 if (stack) { 574 if (stack) {
@@ -510,10 +586,15 @@ void map_stub_pages(int fd, unsigned long code,
510 .offset = map_offset 586 .offset = map_offset
511 } } }); 587 } } });
512 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); 588 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
513 if (n != sizeof(mmop)) 589 if (n != sizeof(mmop)) {
514 panic("map_stub_pages : /proc/mm map for data failed, " 590 n = errno;
515 "err = %d\n", errno); 591 printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
592 "data failed, err = %d\n", n);
593 return -n;
594 }
516 } 595 }
596
597 return 0;
517} 598}
518 599
519void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) 600void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
@@ -574,7 +655,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
574 kmalloc_ok = 0; 655 kmalloc_ok = 0;
575 return 1; 656 return 1;
576 default: 657 default:
577 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 658 printk(UM_KERN_ERR "Bad sigsetjmp return in "
659 "start_idle_thread - %d\n", n);
660 fatal_sigsegv();
578 } 661 }
579 longjmp(*switch_buf, 1); 662 longjmp(*switch_buf, 1);
580} 663}
@@ -617,9 +700,11 @@ void __switch_mm(struct mm_id *mm_idp)
617 if (proc_mm) { 700 if (proc_mm) {
618 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, 701 err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
619 mm_idp->u.mm_fd); 702 mm_idp->u.mm_fd);
620 if (err) 703 if (err) {
621 panic("__switch_mm - PTRACE_SWITCH_MM failed, " 704 printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
622 "errno = %d\n", errno); 705 "failed, errno = %d\n", errno);
706 fatal_sigsegv();
707 }
623 } 708 }
624 else userspace_pid[0] = mm_idp->u.pid; 709 else userspace_pid[0] = mm_idp->u.pid;
625} 710}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b07887c36bb0..6d56d15884fd 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -411,7 +411,9 @@ static inline void check_skas3_ptrace_faultinfo(void)
411 non_fatal("found\n"); 411 non_fatal("found\n");
412 } 412 }
413 413
414 init_registers(pid); 414 if (init_registers(pid))
415 fatal("Failed to initialize default registers");
416
415 stop_ptraced_child(pid, 1, 1); 417 stop_ptraced_child(pid, 1, 1);
416} 418}
417 419
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index e437ee2215c5..f1199fd34d38 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
48 switch (code) { 48 switch (code) {
49 case ARCH_SET_FS: 49 case ARCH_SET_FS:
50 case ARCH_SET_GS: 50 case ARCH_SET_GS:
51 restore_registers(pid, &current->thread.regs.regs); 51 ret = restore_registers(pid, &current->thread.regs.regs);
52 if (ret)
53 return ret;
52 break; 54 break;
53 case ARCH_GET_FS: 55 case ARCH_GET_FS:
54 case ARCH_GET_GS: 56 case ARCH_GET_GS:
@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
70 switch (code) { 72 switch (code) {
71 case ARCH_SET_FS: 73 case ARCH_SET_FS:
72 current->thread.arch.fs = (unsigned long) ptr; 74 current->thread.arch.fs = (unsigned long) ptr;
73 save_registers(pid, &current->thread.regs.regs); 75 ret = save_registers(pid, &current->thread.regs.regs);
74 break; 76 break;
75 case ARCH_SET_GS: 77 case ARCH_SET_GS:
76 save_registers(pid, &current->thread.regs.regs); 78 ret = save_registers(pid, &current->thread.regs.regs);
77 break; 79 break;
78 case ARCH_GET_FS: 80 case ARCH_GET_FS:
79 ret = put_user(tmp, addr); 81 ret = put_user(tmp, addr);