summary refs log tree commit diff
path: root/arch/mips
diff options
context:
space:
mode:
authorLeonid Yegoshin <Leonid.Yegoshin@imgtec.com>2013-12-04 16:39:34 +0000
committerRalf Baechle <ralf@linux-mips.org>2014-03-26 23:09:13 +0100
commit078dde5e21dba9f4186ebfc2aef06341fd20efb4 (patch)
tree7d2bcea5f8bfc5bdc8bbe0a525ab7359e6721a25 /arch/mips
parentb08a9c95f80f2f760f62d70fcd5a869c425d17b6 (diff)
downloadlinux-078dde5e21dba9f4186ebfc2aef06341fd20efb4.tar.gz
MIPS: traps: Set correct address limit for breakpoints and traps
When a breakpoint or trap happens when operating in kernel mode but
on users behalf (eg syscall) it is necessary to change the address
limit to KERNEL_DS so any address checking can be bypassed and print
the correct stack trace.

Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/traps.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 1a76d114e84b..074e857ced28 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -865,6 +865,11 @@ asmlinkage void do_bp(struct pt_regs *regs)
 	enum ctx_state prev_state;
 	unsigned long epc;
 	u16 instr[2];
+	mm_segment_t seg;
+
+	seg = get_fs();
+	if (!user_mode(regs))
+		set_fs(KERNEL_DS);
 
 	prev_state = exception_enter();
 	if (get_isa16_mode(regs->cp0_epc)) {
@@ -924,6 +929,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
 	do_trap_or_bp(regs, bcode, "Break");
 
 out:
+	set_fs(seg);
 	exception_exit(prev_state);
 	return;
 
@@ -937,8 +943,13 @@ asmlinkage void do_tr(struct pt_regs *regs)
 	u32 opcode, tcode = 0;
 	enum ctx_state prev_state;
 	u16 instr[2];
+	mm_segment_t seg;
 	unsigned long epc = msk_isa16_mode(exception_epc(regs));
 
+	seg = get_fs();
+	if (!user_mode(regs))
+		set_fs(get_ds());
+
 	prev_state = exception_enter();
 	if (get_isa16_mode(regs->cp0_epc)) {
 		if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
@@ -959,6 +970,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
 	do_trap_or_bp(regs, tcode, "Trap");
 
 out:
+	set_fs(seg);
 	exception_exit(prev_state);
 	return;