diff options
| -rw-r--r-- | fs/exec.c | 2 | ||||
| -rw-r--r-- | include/linux/ptrace.h | 1 | ||||
| -rw-r--r-- | kernel/ptrace.c | 25 |
3 files changed, 17 insertions, 11 deletions
| @@ -1403,7 +1403,7 @@ static void zap_threads (struct mm_struct *mm) | |||
| 1403 | do_each_thread(g,p) { | 1403 | do_each_thread(g,p) { |
| 1404 | if (mm == p->mm && p != tsk && | 1404 | if (mm == p->mm && p != tsk && |
| 1405 | p->ptrace && p->parent->mm == mm) { | 1405 | p->ptrace && p->parent->mm == mm) { |
| 1406 | __ptrace_unlink(p); | 1406 | __ptrace_detach(p, 0); |
| 1407 | } | 1407 | } |
| 1408 | } while_each_thread(g,p); | 1408 | } while_each_thread(g,p); |
| 1409 | write_unlock_irq(&tasklist_lock); | 1409 | write_unlock_irq(&tasklist_lock); |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 9d5cd106b344..0d36750fc0f1 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
| @@ -84,6 +84,7 @@ extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __us | |||
| 84 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); | 84 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); |
| 85 | extern int ptrace_attach(struct task_struct *tsk); | 85 | extern int ptrace_attach(struct task_struct *tsk); |
| 86 | extern int ptrace_detach(struct task_struct *, unsigned int); | 86 | extern int ptrace_detach(struct task_struct *, unsigned int); |
| 87 | extern void __ptrace_detach(struct task_struct *, unsigned int); | ||
| 87 | extern void ptrace_disable(struct task_struct *); | 88 | extern void ptrace_disable(struct task_struct *); |
| 88 | extern int ptrace_check_attach(struct task_struct *task, int kill); | 89 | extern int ptrace_check_attach(struct task_struct *task, int kill); |
| 89 | extern int ptrace_request(struct task_struct *child, long request, long addr, long data); | 90 | extern int ptrace_request(struct task_struct *child, long request, long addr, long data); |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index d2cf144d0af5..d95a72c9279d 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -72,8 +72,8 @@ void ptrace_untrace(task_t *child) | |||
| 72 | */ | 72 | */ |
| 73 | void __ptrace_unlink(task_t *child) | 73 | void __ptrace_unlink(task_t *child) |
| 74 | { | 74 | { |
| 75 | if (!child->ptrace) | 75 | BUG_ON(!child->ptrace); |
| 76 | BUG(); | 76 | |
| 77 | child->ptrace = 0; | 77 | child->ptrace = 0; |
| 78 | if (!list_empty(&child->ptrace_list)) { | 78 | if (!list_empty(&child->ptrace_list)) { |
| 79 | list_del_init(&child->ptrace_list); | 79 | list_del_init(&child->ptrace_list); |
| @@ -184,22 +184,27 @@ bad: | |||
| 184 | return retval; | 184 | return retval; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | void __ptrace_detach(struct task_struct *child, unsigned int data) | ||
| 188 | { | ||
| 189 | child->exit_code = data; | ||
| 190 | /* .. re-parent .. */ | ||
| 191 | __ptrace_unlink(child); | ||
| 192 | /* .. and wake it up. */ | ||
| 193 | if (child->exit_state != EXIT_ZOMBIE) | ||
| 194 | wake_up_process(child); | ||
| 195 | } | ||
| 196 | |||
| 187 | int ptrace_detach(struct task_struct *child, unsigned int data) | 197 | int ptrace_detach(struct task_struct *child, unsigned int data) |
| 188 | { | 198 | { |
| 189 | if (!valid_signal(data)) | 199 | if (!valid_signal(data)) |
| 190 | return -EIO; | 200 | return -EIO; |
| 191 | 201 | ||
| 192 | /* Architecture-specific hardware disable .. */ | 202 | /* Architecture-specific hardware disable .. */ |
| 193 | ptrace_disable(child); | 203 | ptrace_disable(child); |
| 194 | 204 | ||
| 195 | /* .. re-parent .. */ | ||
| 196 | child->exit_code = data; | ||
| 197 | |||
| 198 | write_lock_irq(&tasklist_lock); | 205 | write_lock_irq(&tasklist_lock); |
| 199 | __ptrace_unlink(child); | 206 | if (child->ptrace) |
| 200 | /* .. and wake it up. */ | 207 | __ptrace_detach(child, data); |
| 201 | if (child->exit_state != EXIT_ZOMBIE) | ||
| 202 | wake_up_process(child); | ||
| 203 | write_unlock_irq(&tasklist_lock); | 208 | write_unlock_irq(&tasklist_lock); |
| 204 | 209 | ||
| 205 | return 0; | 210 | return 0; |
