diff options
Diffstat (limited to 'arch/um/kernel')
| -rw-r--r-- | arch/um/kernel/irq.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/process.c | 13 | ||||
| -rw-r--r-- | arch/um/kernel/ptrace.c | 71 | ||||
| -rw-r--r-- | arch/um/kernel/sigio.c | 3 | ||||
| -rw-r--r-- | arch/um/kernel/skas/syscall.c | 6 | ||||
| -rw-r--r-- | arch/um/kernel/time.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/trap.c | 39 | 
7 files changed, 72 insertions, 64 deletions
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 00506c3d5d6e..9883026f0730 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds;  extern void free_irqs(void); -void sigio_handler(int sig, struct uml_pt_regs *regs) +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)  {  	struct irq_fd *irq_fd;  	int n; diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index ccb9a9d283f1..57fc7028714a 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -151,12 +151,10 @@ void new_thread_handler(void)  	 * 0 if it just exits  	 */  	n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); -	if (n == 1) { -		/* Handle any immediate reschedules or signals */ -		interrupt_end(); +	if (n == 1)  		userspace(¤t->thread.regs.regs); -	} -	else do_exit(0); +	else +		do_exit(0);  }  /* Called magically, see new_thread_handler above */ @@ -175,9 +173,6 @@ void fork_handler(void)  	current->thread.prev_sched = NULL; -	/* Handle any immediate reschedules or signals */ -	interrupt_end(); -  	userspace(¤t->thread.regs.regs);  } @@ -193,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	if (current->thread.forking) {  	  	memcpy(&p->thread.regs.regs, ®s->regs,  		       sizeof(p->thread.regs.regs)); -		UPT_SET_SYSCALL_RETURN(&p->thread.regs.regs, 0); +		PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);  		if (sp != 0)  			REGS_SP(p->thread.regs.regs.gp) = sp; diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 06b190390505..694d551c8899 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -3,11 +3,12 @@   * Licensed under the GPL   */ -#include "linux/audit.h" -#include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "skas_ptrace.h" +#include <linux/audit.h> +#include <linux/ptrace.h> +#include <linux/sched.h> +#include <linux/tracehook.h> +#include <asm/uaccess.h> +#include <skas_ptrace.h> @@ -162,48 +163,36 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,   * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and   * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check   */ -void syscall_trace(struct uml_pt_regs *regs, int entryexit) +void syscall_trace_enter(struct pt_regs *regs)  { -	int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; -	int tracesysgood; - -	if (!entryexit) -		audit_syscall_entry(HOST_AUDIT_ARCH, -				    UPT_SYSCALL_NR(regs), -				    UPT_SYSCALL_ARG1(regs), -				    UPT_SYSCALL_ARG2(regs), -				    UPT_SYSCALL_ARG3(regs), -				    UPT_SYSCALL_ARG4(regs)); -	else -		audit_syscall_exit(regs); - -	/* Fake a debug trap */ -	if (is_singlestep) -		send_sigtrap(current, regs, 0); +	audit_syscall_entry(HOST_AUDIT_ARCH, +			    UPT_SYSCALL_NR(®s->regs), +			    UPT_SYSCALL_ARG1(®s->regs), +			    UPT_SYSCALL_ARG2(®s->regs), +			    UPT_SYSCALL_ARG3(®s->regs), +			    UPT_SYSCALL_ARG4(®s->regs));  	if (!test_thread_flag(TIF_SYSCALL_TRACE))  		return; -	if (!(current->ptrace & PT_PTRACED)) -		return; +	tracehook_report_syscall_entry(regs); +} -	/* -	 * the 0x80 provides a way for the tracing parent to distinguish -	 * between a syscall stop and SIGTRAP delivery -	 */ -	tracesysgood = (current->ptrace & PT_TRACESYSGOOD); -	ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); +void syscall_trace_leave(struct pt_regs *regs) +{ +	int ptraced = current->ptrace; -	if (entryexit) /* force do_signal() --> is_syscall() */ -		set_thread_flag(TIF_SIGPENDING); +	audit_syscall_exit(regs); -	/* -	 * this isn't the same as continuing with a signal, but it will do -	 * for normal use.  strace only continues with a signal if the -	 * stopping signal is not SIGTRAP.  -brl -	 */ -	if (current->exit_code) { -		send_sig(current->exit_code, current, 1); -		current->exit_code = 0; -	} +	/* Fake a debug trap */ +	if (ptraced & PT_DTRACE) +		send_sigtrap(current, ®s->regs, 0); + +	if (!test_thread_flag(TIF_SYSCALL_TRACE)) +		return; + +	tracehook_report_syscall_exit(regs, 0); +	/* force do_signal() --> is_syscall() */ +	if (ptraced & PT_PTRACED) +		set_thread_flag(TIF_SIGPENDING);  } diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index 2a1639255763..c88211139a51 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c @@ -25,8 +25,7 @@ int write_sigio_irq(int fd)  	int err;  	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, -			     IRQF_SAMPLE_RANDOM, "write sigio", -			     NULL); +			     0, "write sigio", NULL);  	if (err) {  		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "  		       "err = %d\n", err); diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 05fbeb480e0b..86368a025a96 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -18,7 +18,7 @@ void handle_syscall(struct uml_pt_regs *r)  	long result;  	int syscall; -	syscall_trace(r, 0); +	syscall_trace_enter(regs);  	/*  	 * This should go in the declaration of syscall, but when I do that, @@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r)  		result = -ENOSYS;  	else result = EXECUTE_SYSCALL(syscall, regs); -	UPT_SET_SYSCALL_RETURN(r, result); +	PT_REGS_SET_SYSCALL_RETURN(regs, result); -	syscall_trace(r, 1); +	syscall_trace_leave(regs);  } diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index d1a23fb3190d..5f76d4ba151c 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -13,7 +13,7 @@  #include "kern_util.h"  #include "os.h" -void timer_handler(int sig, struct uml_pt_regs *regs) +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)  {  	unsigned long flags; diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 3be60765c0e2..0353b98ae35a 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -172,7 +172,7 @@ void fatal_sigsegv(void)  	os_dump_core();  } -void segv_handler(int sig, struct uml_pt_regs *regs) +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)  {  	struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -258,8 +258,11 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,  	return 0;  } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)  { +	struct faultinfo *fi; +	struct siginfo clean_si; +  	if (!UPT_IS_USER(regs)) {  		if (sig == SIGBUS)  			printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -269,18 +272,40 @@ void relay_signal(int sig, struct uml_pt_regs *regs)  	arch_examine_signal(sig, regs); -	current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); -	force_sig(sig, current); +	memset(&clean_si, 0, sizeof(clean_si)); +	clean_si.si_signo = si->si_signo; +	clean_si.si_errno = si->si_errno; +	clean_si.si_code = si->si_code; +	switch (sig) { +	case SIGILL: +	case SIGFPE: +	case SIGSEGV: +	case SIGBUS: +	case SIGTRAP: +		fi = UPT_FAULTINFO(regs); +		clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); +		current->thread.arch.faultinfo = *fi; +#ifdef __ARCH_SI_TRAPNO +		clean_si.si_trapno = si->si_trapno; +#endif +		break; +	default: +		printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", +			sig, si->si_code); +	} + +	force_sig_info(sig, &clean_si, current);  } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)  {  	if (current->thread.fault_catcher != NULL)  		UML_LONGJMP(current->thread.fault_catcher, 1); -	else relay_signal(sig, regs); +	else +		relay_signal(sig, si, regs);  } -void winch(int sig, struct uml_pt_regs *regs) +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)  {  	do_IRQ(WINCH_IRQ, regs);  }  | 
