浏览代码

[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 年之前
父节点
当前提交
d5a2601734
共有 2 个文件被更改,包括 2 次插入2 次删除
  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) ||