Kyle McMartin 07d332
From: Oleg Nesterov <oleg@redhat.com>
Kyle McMartin 07d332
Kyle McMartin 07d332
[PATCH] signals: check ->group_stop_count after tracehook_get_signal()
Kyle McMartin 07d332
Kyle McMartin 07d332
Move the call to do_signal_stop() down, after tracehook call.
Kyle McMartin 07d332
This makes ->group_stop_count condition visible to tracers before
Kyle McMartin 07d332
do_signal_stop() will participate in this group-stop.
Kyle McMartin 07d332
Kyle McMartin 07d332
Currently the patch has no effect, tracehook_get_signal() always
Kyle McMartin 07d332
returns 0.
Kyle McMartin 07d332
Kyle McMartin 07d332
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Kyle McMartin 07d332
Signed-off-by: Roland McGrath <roland@redhat.com>
Kyle McMartin 07d332
---
Kyle McMartin 07d332
 include/linux/ptrace.h    |    1 +
Kyle McMartin 07d332
 include/linux/sched.h     |    1 +
Kyle McMartin 07d332
 include/linux/tracehook.h |   10 +++++-----
Kyle McMartin 07d332
 kernel/ptrace.c           |    2 +-
Kyle McMartin 07d332
 kernel/signal.c           |    4 ++--
Kyle McMartin 07d332
 5 files changed, 10 insertions(+), 8 deletions(-)
Kyle McMartin 07d332
Kyle McMartin 07d332
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
Kyle McMartin 71f70c
index 092a04f..619cdf0 100644  
Kyle McMartin 07d332
--- a/include/linux/ptrace.h
Kyle McMartin 07d332
+++ b/include/linux/ptrace.h
Kyle McMartin 71f70c
@@ -106,6 +106,7 @@ extern int ptrace_traceme(void);
Kyle McMartin 07d332
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
Kyle McMartin 07d332
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
Kyle McMartin 07d332
 extern int ptrace_attach(struct task_struct *tsk);
Kyle McMartin 07d332
+extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee);
Kyle McMartin 07d332
 extern int ptrace_detach(struct task_struct *, unsigned int);
Kyle McMartin 07d332
 extern void ptrace_disable(struct task_struct *);
Kyle McMartin 07d332
 extern int ptrace_check_attach(struct task_struct *task, int kill);
Kyle McMartin 07d332
diff --git a/include/linux/sched.h b/include/linux/sched.h
Kyle McMartin 71f70c
index 2238745..09f26df 100644  
Kyle McMartin 07d332
--- a/include/linux/sched.h
Kyle McMartin 07d332
+++ b/include/linux/sched.h
Kyle McMartin 71f70c
@@ -2061,6 +2061,7 @@ extern int kill_pgrp(struct pid *pid, in
Kyle McMartin 07d332
 extern int kill_pid(struct pid *pid, int sig, int priv);
Kyle McMartin 07d332
 extern int kill_proc_info(int, struct siginfo *, pid_t);
Kyle McMartin 07d332
 extern int do_notify_parent(struct task_struct *, int);
Kyle McMartin 07d332
+extern void do_notify_parent_cldstop(struct task_struct *, int);
Kyle McMartin 07d332
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
Kyle McMartin 07d332
 extern void force_sig(int, struct task_struct *);
Kyle McMartin 07d332
 extern int send_sig(int, struct task_struct *, int);
Kyle McMartin 07d332
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
Kyle McMartin 71f70c
index 3a2e66d..98917e9 100644  
Kyle McMartin 07d332
--- a/include/linux/tracehook.h
Kyle McMartin 07d332
+++ b/include/linux/tracehook.h
Kyle McMartin 07d332
@@ -134,7 +134,7 @@ static inline __must_check int tracehook
Kyle McMartin 07d332
  */
Kyle McMartin 07d332
 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
-	if (step) {
Kyle McMartin 07d332
+	if (step && (task_ptrace(current) & PT_PTRACED)) {
Kyle McMartin 07d332
 		siginfo_t info;
Kyle McMartin 07d332
 		user_single_step_siginfo(current, regs, &info);
Kyle McMartin 07d332
 		force_sig_info(SIGTRAP, &info, current);
Kyle McMartin 07d332
@@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec(
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
 	int unsafe = 0;
Kyle McMartin 07d332
 	int ptrace = task_ptrace(task);
Kyle McMartin 07d332
-	if (ptrace & PT_PTRACED) {
Kyle McMartin 07d332
+	if (ptrace) {
Kyle McMartin 07d332
 		if (ptrace & PT_PTRACE_CAP)
Kyle McMartin 07d332
 			unsafe |= LSM_UNSAFE_PTRACE_CAP;
Kyle McMartin 07d332
 		else
Kyle McMartin 07d332
@@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec(
Kyle McMartin 07d332
  */
Kyle McMartin 07d332
 static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
-	if (task_ptrace(tsk) & PT_PTRACED)
Kyle McMartin 07d332
+	if (task_ptrace(tsk))
Kyle McMartin 07d332
 		return rcu_dereference(tsk->parent);
Kyle McMartin 07d332
 	return NULL;
Kyle McMartin 07d332
 }
Kyle McMartin 07d332
@@ -386,7 +386,7 @@ static inline void tracehook_signal_hand
Kyle McMartin 07d332
 					    const struct k_sigaction *ka,
Kyle McMartin 07d332
 					    struct pt_regs *regs, int stepping)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
-	if (stepping)
Kyle McMartin 07d332
+	if (stepping && (task_ptrace(current) & PT_PTRACED))
Kyle McMartin 07d332
 		ptrace_notify(SIGTRAP);
Kyle McMartin 07d332
 }
Kyle McMartin 07d332
 
Kyle McMartin 07d332
@@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s
Kyle McMartin 07d332
  */
Kyle McMartin 07d332
 static inline int tracehook_notify_jctl(int notify, int why)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
-	return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
Kyle McMartin 07d332
+	return notify ?: task_ptrace(current) ? why : 0;
Kyle McMartin 07d332
 }
Kyle McMartin 07d332
 
Kyle McMartin 07d332
 /**
Kyle McMartin 07d332
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
Kyle McMartin 71f70c
index 99bbaa3..84d9f8f 100644  
Kyle McMartin 07d332
--- a/kernel/ptrace.c
Kyle McMartin 07d332
+++ b/kernel/ptrace.c
Kyle McMartin 07d332
@@ -270,7 +270,7 @@ static int ignoring_children(struct sigh
Kyle McMartin 07d332
  * reap it now, in that case we must also wake up sub-threads sleeping in
Kyle McMartin 07d332
  * do_wait().
Kyle McMartin 07d332
  */
Kyle McMartin 07d332
-static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
Kyle McMartin 07d332
+bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
 	__ptrace_unlink(p);
Kyle McMartin 07d332
 
Kyle McMartin 07d332
diff --git a/kernel/signal.c b/kernel/signal.c
Kyle McMartin 71f70c
index 4e3cff1..b74324d 100644  
Kyle McMartin 07d332
--- a/kernel/signal.c
Kyle McMartin 07d332
+++ b/kernel/signal.c
Kyle McMartin 71f70c
@@ -1522,7 +1522,7 @@ int do_notify_parent(struct task_struct 
Kyle McMartin 07d332
 	return ret;
Kyle McMartin 07d332
 }
Kyle McMartin 07d332
 
Kyle McMartin 07d332
-static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
Kyle McMartin 07d332
+void do_notify_parent_cldstop(struct task_struct *tsk, int why)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
 	struct siginfo info;
Kyle McMartin 07d332
 	unsigned long flags;
Kyle McMartin 71f70c
@@ -1794,7 +1794,7 @@ static int do_signal_stop(int signr)
Kyle McMartin 07d332
 static int ptrace_signal(int signr, siginfo_t *info,
Kyle McMartin 07d332
 			 struct pt_regs *regs, void *cookie)
Kyle McMartin 07d332
 {
Kyle McMartin 07d332
-	if (!task_ptrace(current))
Kyle McMartin 07d332
+	if (!(task_ptrace(current) & PT_PTRACED))
Kyle McMartin 07d332
 		return signr;
Kyle McMartin 07d332
 
Kyle McMartin 07d332
 	ptrace_signal_deliver(regs, cookie);