|
@@ -36,6 +36,7 @@
|
|
#include <linux/sysrq.h>
|
|
#include <linux/sysrq.h>
|
|
#include <linux/nmi.h>
|
|
#include <linux/nmi.h>
|
|
#include <linux/context_tracking.h>
|
|
#include <linux/context_tracking.h>
|
|
|
|
+#include <linux/signal.h>
|
|
|
|
|
|
#include <linux/uaccess.h>
|
|
#include <linux/uaccess.h>
|
|
#include <asm/page.h>
|
|
#include <asm/page.h>
|
|
@@ -521,7 +522,12 @@ static void stack_unaligned(unsigned long sp)
|
|
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0, current);
|
|
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0, current);
|
|
}
|
|
}
|
|
|
|
|
|
-void fault_in_user_windows(void)
|
|
|
|
|
|
+static const char uwfault32[] = KERN_INFO \
|
|
|
|
+ "%s[%d]: bad register window fault: SP %08lx (orig_sp %08lx) TPC %08lx O7 %08lx\n";
|
|
|
|
+static const char uwfault64[] = KERN_INFO \
|
|
|
|
+ "%s[%d]: bad register window fault: SP %016lx (orig_sp %016lx) TPC %08lx O7 %016lx\n";
|
|
|
|
+
|
|
|
|
+void fault_in_user_windows(struct pt_regs *regs)
|
|
{
|
|
{
|
|
struct thread_info *t = current_thread_info();
|
|
struct thread_info *t = current_thread_info();
|
|
unsigned long window;
|
|
unsigned long window;
|
|
@@ -534,9 +540,9 @@ void fault_in_user_windows(void)
|
|
do {
|
|
do {
|
|
struct reg_window *rwin = &t->reg_window[window];
|
|
struct reg_window *rwin = &t->reg_window[window];
|
|
int winsize = sizeof(struct reg_window);
|
|
int winsize = sizeof(struct reg_window);
|
|
- unsigned long sp;
|
|
|
|
|
|
+ unsigned long sp, orig_sp;
|
|
|
|
|
|
- sp = t->rwbuf_stkptrs[window];
|
|
|
|
|
|
+ orig_sp = sp = t->rwbuf_stkptrs[window];
|
|
|
|
|
|
if (test_thread_64bit_stack(sp))
|
|
if (test_thread_64bit_stack(sp))
|
|
sp += STACK_BIAS;
|
|
sp += STACK_BIAS;
|
|
@@ -547,8 +553,16 @@ void fault_in_user_windows(void)
|
|
stack_unaligned(sp);
|
|
stack_unaligned(sp);
|
|
|
|
|
|
if (unlikely(copy_to_user((char __user *)sp,
|
|
if (unlikely(copy_to_user((char __user *)sp,
|
|
- rwin, winsize)))
|
|
|
|
|
|
+ rwin, winsize))) {
|
|
|
|
+ if (show_unhandled_signals)
|
|
|
|
+ printk_ratelimited(is_compat_task() ?
|
|
|
|
+ uwfault32 : uwfault64,
|
|
|
|
+ current->comm, current->pid,
|
|
|
|
+ sp, orig_sp,
|
|
|
|
+ regs->tpc,
|
|
|
|
+ regs->u_regs[UREG_I7]);
|
|
goto barf;
|
|
goto barf;
|
|
|
|
+ }
|
|
} while (window--);
|
|
} while (window--);
|
|
}
|
|
}
|
|
set_thread_wsaved(0);
|
|
set_thread_wsaved(0);
|
|
@@ -556,8 +570,7 @@ void fault_in_user_windows(void)
|
|
|
|
|
|
barf:
|
|
barf:
|
|
set_thread_wsaved(window + 1);
|
|
set_thread_wsaved(window + 1);
|
|
- user_exit();
|
|
|
|
- do_exit(SIGILL);
|
|
|
|
|
|
+ force_sig(SIGSEGV, current);
|
|
}
|
|
}
|
|
|
|
|
|
asmlinkage long sparc_do_fork(unsigned long clone_flags,
|
|
asmlinkage long sparc_do_fork(unsigned long clone_flags,
|