Skip to content

Commit

Permalink
MIPS: Read watch registers with interrupts disabled.
Browse files Browse the repository at this point in the history
If a context switch occurred between the watch exception and reading the
watch registers, it would be possible for the new process to corrupt their
state.  Enabling interrupts only after the watch registers are read avoids
this race.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
David Daney authored and Ralf Baechle committed Jan 30, 2009
1 parent 7adbeda commit 8bc6d05
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
6 changes: 5 additions & 1 deletion arch/mips/kernel/genex.S
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,11 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER fpe fpe fpe silent /* #15 */
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
#ifdef CONFIG_HARDWARE_WATCHPOINTS
BUILD_HANDLER watch watch sti silent /* #23 */
/*
* For watch, interrupts will be enabled after the watch
* registers are read.
*/
BUILD_HANDLER watch watch cli silent /* #23 */
#else
BUILD_HANDLER watch watch sti verbose /* #23 */
#endif
Expand Down
8 changes: 7 additions & 1 deletion arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,9 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
force_sig(SIGILL, current);
}

/*
* Called with interrupts disabled.
*/
asmlinkage void do_watch(struct pt_regs *regs)
{
u32 cause;
Expand All @@ -963,9 +966,12 @@ asmlinkage void do_watch(struct pt_regs *regs)
*/
if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
mips_read_watch_registers();
local_irq_enable();
force_sig(SIGTRAP, current);
} else
} else {
mips_clear_watch_registers();
local_irq_enable();
}
}

asmlinkage void do_mcheck(struct pt_regs *regs)
Expand Down

0 comments on commit 8bc6d05

Please sign in to comment.