This is a note to let you know that I've just added the patch titled
x86, hw_breakpoints: Fix racy access to ptrace breakpoints
to the 2.6.33-longterm tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/longterm/longterm-queue-2.6.33.git;a=summary
The filename of the patch is:
x86-hw_breakpoints-fix-racy-access-to-ptrace-breakpoints.patch
and it can be found in the queue-2.6.33 subdirectory.
If you, or anyone else, feels it should not be added to the 2.6.33 longterm
tree,
please let <[email protected]> know about it.
>From 87dc669ba25777b67796d7262c569429e58b1ed4 Mon Sep 17 00:00:00 2001
From: Frederic Weisbecker <[email protected]>
Date: Fri, 8 Apr 2011 17:29:36 +0200
Subject: x86, hw_breakpoints: Fix racy access to ptrace breakpoints
From: Frederic Weisbecker <[email protected]>
commit 87dc669ba25777b67796d7262c569429e58b1ed4 upstream.
While the tracer accesses ptrace breakpoints, the child task may
concurrently exit due to a SIGKILL and thus release its breakpoints
at the same time. We can then dereference some freed pointers.
To fix this, hold a reference on the child breakpoints before
manipulating them.
Reported-by: Oleg Nesterov <[email protected]>
Signed-off-by: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Prasad <[email protected]>
Cc: Paul Mundt <[email protected]>
Link:
http://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kernel/ptrace.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -635,6 +635,9 @@ static int ptrace_write_dr7(struct task_
unsigned len, type;
struct perf_event *bp;
+ if (ptrace_get_breakpoints(tsk) < 0)
+ return -ESRCH;
+
data &= ~DR_CONTROL_RESERVED;
old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
restore:
@@ -682,6 +685,9 @@ restore:
}
goto restore;
}
+
+ ptrace_put_breakpoints(tsk);
+
return ((orig_ret < 0) ? orig_ret : rc);
}
@@ -695,10 +701,17 @@ static unsigned long ptrace_get_debugreg
if (n < HBP_NUM) {
struct perf_event *bp;
+
+ if (ptrace_get_breakpoints(tsk) < 0)
+ return -ESRCH;
+
bp = thread->ptrace_bps[n];
if (!bp)
- return 0;
- val = bp->hw.info.address;
+ val = 0;
+ else
+ val = bp->hw.info.address;
+
+ ptrace_put_breakpoints(tsk);
} else if (n == 6) {
val = thread->debugreg6;
} else if (n == 7) {
@@ -713,6 +726,10 @@ static int ptrace_set_breakpoint_addr(st
struct perf_event *bp;
struct thread_struct *t = &tsk->thread;
struct perf_event_attr attr;
+ int err = 0;
+
+ if (ptrace_get_breakpoints(tsk) < 0)
+ return -ESRCH;
if (!t->ptrace_bps[nr]) {
hw_breakpoint_init(&attr);
@@ -736,24 +753,23 @@ static int ptrace_set_breakpoint_addr(st
* writing for the user. And anyway this is the previous
* behaviour.
*/
- if (IS_ERR(bp))
- return PTR_ERR(bp);
+ if (IS_ERR(bp)) {
+ err = PTR_ERR(bp);
+ goto put;
+ }
t->ptrace_bps[nr] = bp;
} else {
- int err;
-
bp = t->ptrace_bps[nr];
attr = bp->attr;
attr.bp_addr = addr;
err = modify_user_hw_breakpoint(bp, &attr);
- if (err)
- return err;
}
-
- return 0;
+put:
+ ptrace_put_breakpoints(tsk);
+ return err;
}
/*
Patches currently in longterm-queue-2.6.33 which might be from
[email protected] are
/home/gregkh/linux/longterm/longterm-queue-2.6.33/queue-2.6.33/ptrace-prepare-to-fix-racy-accesses-on-task-breakpoints.patch
/home/gregkh/linux/longterm/longterm-queue-2.6.33/queue-2.6.33/x86-hw_breakpoints-fix-racy-access-to-ptrace-breakpoints.patch
_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable