diff options
Diffstat (limited to 'linux-2.6-tracehook.patch')
-rw-r--r-- | linux-2.6-tracehook.patch | 129 |
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); |