diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-06-26 11:26:07 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 20:58:27 +0400 |
commit | d5f70c00ad24cd1158d3678b44ff969b4c971d49 (patch) | |
tree | b4b71a71b413250fb24cb2d83cbbfd7507da9efc /fs/exec.c | |
parent | 281de339ceb822ca6c04d4373ecb9a45c1890ce4 (diff) | |
download | linux-d5f70c00ad24cd1158d3678b44ff969b4c971d49.tar.xz |
[PATCH] coredump: kill ptrace related stuff
With this patch zap_process() sets SIGNAL_GROUP_EXIT while sending SIGKILL to
the thread group. This means that a TASK_TRACED task
1. Will be awakened by signal_wake_up(1)
2. Can't sleep again via ptrace_notify()
3. Can't go to do_signal_stop() after return
from ptrace_stop() in get_signal_to_deliver()
So we can remove all ptrace related stuff from coredump path.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 30 |
1 files changed, 5 insertions, 25 deletions
diff --git a/fs/exec.c b/fs/exec.c index a5c51646d1ad..b58ba7d127e0 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1368,12 +1368,14 @@ static void format_corename(char *corename, const char *pattern, long signr) *out_ptr = 0; } -static void zap_process(struct task_struct *start, int *ptraced) +static void zap_process(struct task_struct *start) { struct task_struct *t; unsigned long flags; spin_lock_irqsave(&start->sighand->siglock, flags); + start->signal->flags = SIGNAL_GROUP_EXIT; + start->signal->group_stop_count = 0; t = start; do { @@ -1381,22 +1383,17 @@ static void zap_process(struct task_struct *start, int *ptraced) t->mm->core_waiters++; sigaddset(&t->pending.signal, SIGKILL); signal_wake_up(t, 1); - - if (unlikely(t->ptrace) && - unlikely(t->parent->mm == t->mm)) - *ptraced = 1; } } while ((t = next_thread(t)) != start); spin_unlock_irqrestore(&start->sighand->siglock, flags); } -static void zap_threads (struct mm_struct *mm) +static void zap_threads(struct mm_struct *mm) { struct task_struct *g, *p; struct task_struct *tsk = current; struct completion *vfork_done = tsk->vfork_done; - int traced = 0; /* * Make sure nobody is waiting for us to release the VM, @@ -1413,29 +1410,12 @@ static void zap_threads (struct mm_struct *mm) do { if (p->mm) { if (p->mm == mm) - zap_process(p, &traced); + zap_process(p); break; } } while ((p = next_thread(p)) != g); } read_unlock(&tasklist_lock); - - if (unlikely(traced)) { - /* - * We are zapping a thread and the thread it ptraces. - * If the tracee went into a ptrace stop for exit tracing, - * we could deadlock since the tracer is waiting for this - * coredump to finish. Detach them so they can both die. - */ - write_lock_irq(&tasklist_lock); - do_each_thread(g,p) { - if (mm == p->mm && p != tsk && - p->ptrace && p->parent->mm == mm) { - __ptrace_detach(p, 0); - } - } while_each_thread(g,p); - write_unlock_irq(&tasklist_lock); - } } static void coredump_wait(struct mm_struct *mm) |