[PATCH 25/33] teach ptrace_set_syscall_trace() to play well with utrace

Oleg Nesterov oleg at redhat.com
Mon Nov 21 20:02:33 UTC 2011


1. ptrace_set_syscall_trace(true)->set_tsk_thread_flag(TIF_SYSCALL_TRACE)
   can race with utrace_control()->utrace_reset() path which can miss
   PT_SYSCALL_TRACE and clear TIF_SYSCALL_TRACE after it was already set.

2. ptrace_set_syscall_trace(false) clears TIF_SYSCALL_TRACE and this is
   not utrace-friendly, it can need this flag.

Change ptrace_set_syscall_trace() to take task_utrace_lock(), this is
enough to fix the 1st problem. Check task_utrace_flags() before clearing
TIF_SYSCALL_TRACE, this fixes 2.

Signed-off-by: Oleg Nesterov <oleg at redhat.com>
---
 kernel/ptrace.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1ac03eb..739183a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -24,6 +24,7 @@
 #include <linux/regset.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/cn_proc.h>
+#include <linux/utrace.h>
 
 void ptrace_signal_wake_up(struct task_struct *p, int quiescent)
 {
@@ -40,13 +41,16 @@ void ptrace_signal_wake_up(struct task_struct *p, int quiescent)
 
 static void ptrace_set_syscall_trace(struct task_struct *p, bool on)
 {
+	task_utrace_lock(p);
 	if (on) {
 		p->ptrace |= PT_SYSCALL_TRACE;
 		set_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
 	} else {
 		p->ptrace &= ~PT_SYSCALL_TRACE;
-		clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
+		if (!(task_utrace_flags(p) & UTRACE_EVENT_SYSCALL))
+			clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
 	}
+	task_utrace_unlock(p);
 }
 
 static int ptrace_trapping_sleep_fn(void *flags)
-- 
1.5.5.1



More information about the kernel mailing list