diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2005-11-23 16:37:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-23 19:08:39 -0500 |
commit | 962b564cf1ec8041e8890a3c3847e3a630a08f42 (patch) | |
tree | a238616355c02496177e486d78f9a75911e943b6 | |
parent | 8bf1101bd52573e0573e374d56d2feecdbb5e444 (diff) |
[PATCH] fix do_wait() vs exec() race
When non-leader thread does exec, de_thread adds old leader to the init's
->children list in EXIT_ZOMBIE state and drops tasklist_lock.
This means that release_task(leader) in de_thread() is racy vs do_wait()
from init task.
I think de_thread() should set old leader's state to EXIT_DEAD instead.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: george anzinger <george@mvista.com>
Cc: Roland Dreier <rolandd@cisco.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/exec.c | 8 |
1 files changed, 4 insertions, 4 deletions
@@ -668,7 +668,7 @@ static inline int de_thread(struct task_struct *tsk) | |||
668 | if (!thread_group_leader(current)) { | 668 | if (!thread_group_leader(current)) { |
669 | struct task_struct *parent; | 669 | struct task_struct *parent; |
670 | struct dentry *proc_dentry1, *proc_dentry2; | 670 | struct dentry *proc_dentry1, *proc_dentry2; |
671 | unsigned long exit_state, ptrace; | 671 | unsigned long ptrace; |
672 | 672 | ||
673 | /* | 673 | /* |
674 | * Wait for the thread group leader to be a zombie. | 674 | * Wait for the thread group leader to be a zombie. |
@@ -726,15 +726,15 @@ static inline int de_thread(struct task_struct *tsk) | |||
726 | list_del(¤t->tasks); | 726 | list_del(¤t->tasks); |
727 | list_add_tail(¤t->tasks, &init_task.tasks); | 727 | list_add_tail(¤t->tasks, &init_task.tasks); |
728 | current->exit_signal = SIGCHLD; | 728 | current->exit_signal = SIGCHLD; |
729 | exit_state = leader->exit_state; | 729 | |
730 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); | ||
731 | leader->exit_state = EXIT_DEAD; | ||
730 | 732 | ||
731 | write_unlock_irq(&tasklist_lock); | 733 | write_unlock_irq(&tasklist_lock); |
732 | spin_unlock(&leader->proc_lock); | 734 | spin_unlock(&leader->proc_lock); |
733 | spin_unlock(¤t->proc_lock); | 735 | spin_unlock(¤t->proc_lock); |
734 | proc_pid_flush(proc_dentry1); | 736 | proc_pid_flush(proc_dentry1); |
735 | proc_pid_flush(proc_dentry2); | 737 | proc_pid_flush(proc_dentry2); |
736 | |||
737 | BUG_ON(exit_state != EXIT_ZOMBIE); | ||
738 | } | 738 | } |
739 | 739 | ||
740 | /* | 740 | /* |