Browse Source

[PATCH] i386/x86-64: Add user_mode checks to profile_pc for oprofile

Fixes a obscure user space triggerable crash during oprofiling.

Oprofile calls profile_pc from NMIs even when user_mode(regs) is not true and
the program counter is inside the kernel lock section. This opens
a race - when a user program jumps to a kernel lock address and
a NMI happens before the illegal page fault exception is raised
and the program has a unmapped esp or ebp then the kernel could
oops. NMIs have a higher priority than exceptions so that could
happen.

Add user_mode checks to i386/x86-64 profile_pc to prevent that.

Cc: John Levon <levon@movementarian.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Andi Kleen 19 years ago
parent
commit
d5a2601734
2 changed files with 2 additions and 2 deletions
  1. 1 1
      arch/i386/kernel/time.c
  2. 1 1
      arch/x86_64/kernel/time.c

+ 1 - 1
arch/i386/kernel/time.c

@@ -135,7 +135,7 @@ unsigned long profile_pc(struct pt_regs *regs)
 {
 {
 	unsigned long pc = instruction_pointer(regs);
 	unsigned long pc = instruction_pointer(regs);
 
 
-	if (in_lock_functions(pc))
+	if (!user_mode_vm(regs) && in_lock_functions(pc))
 		return *(unsigned long *)(regs->ebp + 4);
 		return *(unsigned long *)(regs->ebp + 4);
 
 
 	return pc;
 	return pc;

+ 1 - 1
arch/x86_64/kernel/time.c

@@ -193,7 +193,7 @@ unsigned long profile_pc(struct pt_regs *regs)
 	   is just accounted to the spinlock function.
 	   is just accounted to the spinlock function.
 	   Better would be to write these functions in assembler again
 	   Better would be to write these functions in assembler again
 	   and check exactly. */
 	   and check exactly. */
-	if (in_lock_functions(pc)) {
+	if (!user_mode(regs) && in_lock_functions(pc)) {
 		char *v = *(char **)regs->rsp;
 		char *v = *(char **)regs->rsp;
 		if ((v >= _stext && v <= _etext) ||
 		if ((v >= _stext && v <= _etext) ||
 			(v >= _sinittext && v <= _einittext) ||
 			(v >= _sinittext && v <= _einittext) ||