| 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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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); |