summaryrefslogtreecommitdiffstats
path: root/linux-2.6-tracehook.patch
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.6-tracehook.patch')
-rw-r--r--linux-2.6-tracehook.patch129
1 files changed, 129 insertions, 0 deletions
diff --git a/linux-2.6-tracehook.patch b/linux-2.6-tracehook.patch
new file mode 100644
index 000000000..b4928fcae
--- /dev/null
+++ b/linux-2.6-tracehook.patch
@@ -0,0 +1,129 @@
+From: Oleg Nesterov <oleg@redhat.com>
+
+[PATCH] signals: check ->group_stop_count after tracehook_get_signal()
+
+Move the call to do_signal_stop() down, after tracehook call.
+This makes ->group_stop_count condition visible to tracers before
+do_signal_stop() will participate in this group-stop.
+
+Currently the patch has no effect, tracehook_get_signal() always
+returns 0.
+
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Roland McGrath <roland@redhat.com>
+---
+ include/linux/ptrace.h | 1 +
+ include/linux/sched.h | 1 +
+ include/linux/tracehook.h | 10 +++++-----
+ kernel/ptrace.c | 2 +-
+ kernel/signal.c | 4 ++--
+ 5 files changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
+index 4272521..a85fb41 100644
+--- a/include/linux/ptrace.h
++++ b/include/linux/ptrace.h
+@@ -105,6 +105,7 @@ extern int ptrace_traceme(void);
+ extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
+ extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
+ extern int ptrace_attach(struct task_struct *tsk);
++extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee);
+ extern int ptrace_detach(struct task_struct *, unsigned int);
+ extern void ptrace_disable(struct task_struct *);
+ extern int ptrace_check_attach(struct task_struct *task, int kill);
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index ce160d6..5e7cc95 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2030,6 +2030,7 @@ extern int kill_pgrp(struct pid *pid, in
+ extern int kill_pid(struct pid *pid, int sig, int priv);
+ extern int kill_proc_info(int, struct siginfo *, pid_t);
+ extern int do_notify_parent(struct task_struct *, int);
++extern void do_notify_parent_cldstop(struct task_struct *, int);
+ extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
+ extern void force_sig(int, struct task_struct *);
+ extern int send_sig(int, struct task_struct *, int);
+diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
+index 10db010..c78b2f4 100644
+--- a/include/linux/tracehook.h
++++ b/include/linux/tracehook.h
+@@ -134,7 +134,7 @@ static inline __must_check int tracehook
+ */
+ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
+ {
+- if (step) {
++ if (step && (task_ptrace(current) & PT_PTRACED)) {
+ siginfo_t info;
+ user_single_step_siginfo(current, regs, &info);
+ force_sig_info(SIGTRAP, &info, current);
+@@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec(
+ {
+ int unsafe = 0;
+ int ptrace = task_ptrace(task);
+- if (ptrace & PT_PTRACED) {
++ if (ptrace) {
+ if (ptrace & PT_PTRACE_CAP)
+ unsafe |= LSM_UNSAFE_PTRACE_CAP;
+ else
+@@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec(
+ */
+ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
+ {
+- if (task_ptrace(tsk) & PT_PTRACED)
++ if (task_ptrace(tsk))
+ return rcu_dereference(tsk->parent);
+ return NULL;
+ }
+@@ -386,7 +386,7 @@ static inline void tracehook_signal_hand
+ const struct k_sigaction *ka,
+ struct pt_regs *regs, int stepping)
+ {
+- if (stepping)
++ if (stepping && (task_ptrace(current) & PT_PTRACED))
+ ptrace_notify(SIGTRAP);
+ }
+
+@@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s
+ */
+ static inline int tracehook_notify_jctl(int notify, int why)
+ {
+- return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
++ return notify ?: task_ptrace(current) ? why : 0;
+ }
+
+ /**
+diff --git a/kernel/ptrace.c b/kernel/ptrace.c
+index f34d798..8049cb5 100644
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -270,7 +270,7 @@ static int ignoring_children(struct sigh
+ * reap it now, in that case we must also wake up sub-threads sleeping in
+ * do_wait().
+ */
+-static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
++bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
+ {
+ __ptrace_unlink(p);
+
+diff --git a/kernel/signal.c b/kernel/signal.c
+index bded651..6d13d9f 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1521,7 +1521,7 @@ int do_notify_parent(struct task_struct
+ return ret;
+ }
+
+-static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
++void do_notify_parent_cldstop(struct task_struct *tsk, int why)
+ {
+ struct siginfo info;
+ unsigned long flags;
+@@ -1791,7 +1791,7 @@ static int do_signal_stop(int signr)
+ static int ptrace_signal(int signr, siginfo_t *info,
+ struct pt_regs *regs, void *cookie)
+ {
+- if (!task_ptrace(current))
++ if (!(task_ptrace(current) & PT_PTRACED))
+ return signr;
+
+ ptrace_signal_deliver(regs, cookie);