diff options
-rw-r--r-- | include/linux/ptrace.h | 4 | ||||
-rw-r--r-- | kernel/exit.c | 9 |
2 files changed, 8 insertions, 5 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index ebe0c17039cf..f98501ba557e 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -98,6 +98,10 @@ extern void ptrace_untrace(struct task_struct *child); | |||
98 | extern int ptrace_may_attach(struct task_struct *task); | 98 | extern int ptrace_may_attach(struct task_struct *task); |
99 | extern int __ptrace_may_attach(struct task_struct *task); | 99 | extern int __ptrace_may_attach(struct task_struct *task); |
100 | 100 | ||
101 | static inline int ptrace_reparented(struct task_struct *child) | ||
102 | { | ||
103 | return child->real_parent != child->parent; | ||
104 | } | ||
101 | static inline void ptrace_link(struct task_struct *child, | 105 | static inline void ptrace_link(struct task_struct *child, |
102 | struct task_struct *new_parent) | 106 | struct task_struct *new_parent) |
103 | { | 107 | { |
diff --git a/kernel/exit.c b/kernel/exit.c index 879ed6e1c883..0da2921b1e7f 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -698,7 +698,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
698 | if (unlikely(traced)) { | 698 | if (unlikely(traced)) { |
699 | /* Preserve ptrace links if someone else is tracing this child. */ | 699 | /* Preserve ptrace links if someone else is tracing this child. */ |
700 | list_del_init(&p->ptrace_list); | 700 | list_del_init(&p->ptrace_list); |
701 | if (p->parent != p->real_parent) | 701 | if (ptrace_reparented(p)) |
702 | list_add(&p->ptrace_list, &p->real_parent->ptrace_children); | 702 | list_add(&p->ptrace_list, &p->real_parent->ptrace_children); |
703 | } else { | 703 | } else { |
704 | /* If this child is being traced, then we're the one tracing it | 704 | /* If this child is being traced, then we're the one tracing it |
@@ -865,8 +865,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
865 | * only has special meaning to our real parent. | 865 | * only has special meaning to our real parent. |
866 | */ | 866 | */ |
867 | if (!task_detached(tsk) && thread_group_empty(tsk)) { | 867 | if (!task_detached(tsk) && thread_group_empty(tsk)) { |
868 | int signal = (tsk->parent == tsk->real_parent) | 868 | int signal = ptrace_reparented(tsk) ? |
869 | ? tsk->exit_signal : SIGCHLD; | 869 | SIGCHLD : tsk->exit_signal; |
870 | do_notify_parent(tsk, signal); | 870 | do_notify_parent(tsk, signal); |
871 | } else if (tsk->ptrace) { | 871 | } else if (tsk->ptrace) { |
872 | do_notify_parent(tsk, SIGCHLD); | 872 | do_notify_parent(tsk, SIGCHLD); |
@@ -1269,8 +1269,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap, | |||
1269 | return 0; | 1269 | return 0; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | /* traced means p->ptrace, but not vice versa */ | 1272 | traced = ptrace_reparented(p); |
1273 | traced = (p->real_parent != p->parent); | ||
1274 | 1273 | ||
1275 | if (likely(!traced)) { | 1274 | if (likely(!traced)) { |
1276 | struct signal_struct *psig; | 1275 | struct signal_struct *psig; |