MIPS: traps: Set correct address limit for breakpoints and traps
authorLeonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Wed, 4 Dec 2013 16:39:34 +0000 (16:39 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 26 Mar 2014 22:09:13 +0000 (23:09 +0100)
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>
arch/mips/kernel/traps.c

index 1a76d114e84bdfcc4171433314345909f58772fa..074e857ced284eb70bab2d8ae31ae496a14984b5 100644 (file)
@@ -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;