3e6f2ac480
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>
68 lines
2 KiB
C
68 lines
2 KiB
C
/*
|
|
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
|
* Licensed under the GPL
|
|
*/
|
|
|
|
#ifndef __KERN_UTIL_H__
|
|
#define __KERN_UTIL_H__
|
|
|
|
#include "sysdep/ptrace.h"
|
|
#include "sysdep/faultinfo.h"
|
|
|
|
extern int ncpus;
|
|
extern int kmalloc_ok;
|
|
extern int nsyscalls;
|
|
|
|
#define UML_ROUND_UP(addr) \
|
|
((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
|
|
|
|
extern unsigned long alloc_stack(int order, int atomic);
|
|
extern void free_stack(unsigned long stack, int order);
|
|
|
|
extern int do_signal(void);
|
|
extern void copy_sc(struct uml_pt_regs *regs, void *from);
|
|
extern void interrupt_end(void);
|
|
extern void relay_signal(int sig, struct uml_pt_regs *regs);
|
|
|
|
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
|
|
int is_user, struct uml_pt_regs *regs);
|
|
extern int handle_page_fault(unsigned long address, unsigned long ip,
|
|
int is_write, int is_user, int *code_out);
|
|
|
|
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
|
|
extern int smp_sigio_handler(void);
|
|
extern void initial_thread_cb(void (*proc)(void *), void *arg);
|
|
extern int is_syscall(unsigned long addr);
|
|
extern void timer_handler(int sig, struct uml_pt_regs *regs);
|
|
|
|
extern void timer_handler(int sig, struct uml_pt_regs *regs);
|
|
|
|
extern int start_uml(void);
|
|
extern void paging_init(void);
|
|
|
|
extern void uml_cleanup(void);
|
|
extern void do_uml_exitcalls(void);
|
|
|
|
/*
|
|
* Are we disallowed to sleep? Used to choose between GFP_KERNEL and
|
|
* GFP_ATOMIC.
|
|
*/
|
|
extern int __cant_sleep(void);
|
|
extern void *get_current(void);
|
|
extern int copy_from_user_proc(void *to, void *from, int size);
|
|
extern int cpu(void);
|
|
extern char *uml_strdup(const char *string);
|
|
|
|
extern unsigned long to_irq_stack(unsigned long *mask_out);
|
|
extern unsigned long from_irq_stack(int nested);
|
|
|
|
extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
|
|
extern int singlestepping(void *t);
|
|
|
|
extern void segv_handler(int sig, struct uml_pt_regs *regs);
|
|
extern void bus_handler(int sig, struct uml_pt_regs *regs);
|
|
extern void winch(int sig, struct uml_pt_regs *regs);
|
|
extern void fatal_sigsegv(void) __attribute__ ((noreturn));
|
|
|
|
|
|
#endif
|