Re: [PATCH] x86, vm86: fix preemption bug for int3 breakpointhandlers.

From: Bart Oldeman
Date: Sat Dec 05 2009 - 10:06:54 EST


Thomas,

On Mon, 25 May 2009, Thomas Gleixner wrote:
On Sun, 24 May 2009, Bart Oldeman wrote:
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -551,8 +551,12 @@ cannot_handle:
int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int
trapno)
{
if (VMPI.is_vm86pus) {
- if ((trapno == 3) || (trapno == 1))
+ if ((trapno == 3) || (trapno == 1)) {
+ /* re-enable preemption: return_to_32bit()
+ jumps straight to entry_32.S */
+ dec_preempt_count();

This will break other callers of handle_vm86_trap().

sorry for the late reply, I was just pointed out by someone else about the
existence of this bug again. You are right of course. Below is a new patch.

Note that on the linux-2.6-x86.git tree, commit 08d68323d1f0c34452e614263b212ca556dae47f ("hw-breakpoints: modifying
generic debug exception to use thread-specific debug registers") broke vm86 debug exceptions as well again. The trouble is that handle_vm86_trap() may jump and change the stack to let the kernel return to 32 bit user space, so the handle_vm86_trap() call itself may not return.

--
Impact: fix kernel bug such as:
May 22 16:47:47 localhost kernel: note: dosemu.bin[5281] exited with preempt_count 1

Commit be716615fe596ee117292dc615e95f707fb67fd1 ("x86, vm86:
fix preemption bug"), fixed the problem for debug exceptions but not for breakpoints. This change also fixes breakpoints.

Cc: stable@xxxxxxxxxx
Signed-off-by: Bart Oldeman <bartoldeman@xxxxxxxxxxxxxxxxxxxxx>
---
arch/x86/kernel/traps.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -181,9 +181,14 @@ kernel_trap:

#ifdef CONFIG_X86_32
vm86_trap:
+ /* reenable preemption: handle_vm86_trap() might sleep */
+ dec_preempt_count();
if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
- error_code, trapnr))
+ error_code, trapnr)) {
+ inc_preempt_count();
goto trap_signal;
+ }
+ inc_preempt_count();
return;
#endif
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/