aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/include
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2008-02-05 01:30:58 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:28 -0500
commit3e6f2ac480ce398ade2fd6b5e02d00d1265f1e0f (patch)
tree25f5589189170c20a765d4e6f0c56b42ad58ea20 /arch/um/include
parentd25f2e1235aab716c9fd6ba36c42503627a3a0e3 (diff)
uml: kill processes instead of panicing kernel
UML was panicing in the case of failures of libc calls which shouldn't happen. This is an overreaction since a failure from libc doesn't normally mean that kernel data structures are in an unknown state. Instead, the current process should just be killed if there is no way to recover. The case that prompted this was a failure of PTRACE_SETREGS restoring the same state that was read by PTRACE_GETREGS. It appears that when a process tries to load a bogus value into a segment register, it segfaults (as expected) and the value is actually loaded and is seen by PTRACE_GETREGS (not expected). This case is fixed by forcing a fatal SIGSEGV on the process so that it immediately dies. fatal_sigsegv was added for this purpose. It was declared as noreturn, so in order to pursuade gcc that it actually does not return, I added a call to os_dump_core (and declared it noreturn) so that I get a core file if somehow the process survives. All other calls in arch/um/os-Linux/skas/process.c got the same treatment, with failures causing the process to die instead of a kernel panic, with some exceptions. userspace_tramp exits with status 1 if anything goes wrong there. That will cause start_userspace to return an error. copy_context_skas0 and map_stub_pages also now return errors instead of panicing. Callers of thes functions were changed to check for errors and do something appropriate. Usually that's to return an error to their callers. check_skas3_ptrace_faultinfo just exits since that's too early to do anything else. save_registers, restore_registers, and init_registers now return status instead of panicing on failure, with their callers doing something appropriate. There were also duplicate declarations of save_registers and restore_registers in os.h - these are gone. I noticed and fixed up some whitespace damage. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/include')
-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
3 files changed, 7 insertions, 8 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