aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2005-11-07 13:12:43 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-08 15:58:38 -0500
commit329f7dba5f7dc3bc9a30ad00cf373d2e83115aa1 (patch)
tree3d8c8b2fd07ad2c1df959421121451207373f78f
parenta52e8381c430896d3bd6065a34fda99cb5c74c82 (diff)
[PATCH] fix de_thread() vs send_group_sigqueue() race
When non-leader thread does exec, de_thread calls release_task(leader) before calling exit_itimers(). If local timer interrupt happens in between, it can oops in send_group_sigqueue() while taking ->sighand->siglock == NULL. However, we can't change send_group_sigqueue() to check p->signal != NULL, because sys_timer_create() does get_task_struct() only in SIGEV_THREAD_ID case. So it is possible that this task_struct was already freed and we can't trust p->signal. This patch changes de_thread() so that leader released after exit_itimers() call. Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru> Acked-by: Chris Wright <chrisw@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/exec.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/exec.c b/fs/exec.c
index cd6c574557dc..5a4e3acc2e9f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -590,6 +590,7 @@ static inline int de_thread(struct task_struct *tsk)
590 struct signal_struct *sig = tsk->signal; 590 struct signal_struct *sig = tsk->signal;
591 struct sighand_struct *newsighand, *oldsighand = tsk->sighand; 591 struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
592 spinlock_t *lock = &oldsighand->siglock; 592 spinlock_t *lock = &oldsighand->siglock;
593 struct task_struct *leader = NULL;
593 int count; 594 int count;
594 595
595 /* 596 /*
@@ -665,7 +666,7 @@ static inline int de_thread(struct task_struct *tsk)
665 * and to assume its PID: 666 * and to assume its PID:
666 */ 667 */
667 if (!thread_group_leader(current)) { 668 if (!thread_group_leader(current)) {
668 struct task_struct *leader = current->group_leader, *parent; 669 struct task_struct *parent;
669 struct dentry *proc_dentry1, *proc_dentry2; 670 struct dentry *proc_dentry1, *proc_dentry2;
670 unsigned long exit_state, ptrace; 671 unsigned long exit_state, ptrace;
671 672
@@ -674,6 +675,7 @@ static inline int de_thread(struct task_struct *tsk)
674 * It should already be zombie at this point, most 675 * It should already be zombie at this point, most
675 * of the time. 676 * of the time.
676 */ 677 */
678 leader = current->group_leader;
677 while (leader->exit_state != EXIT_ZOMBIE) 679 while (leader->exit_state != EXIT_ZOMBIE)
678 yield(); 680 yield();
679 681
@@ -733,7 +735,6 @@ static inline int de_thread(struct task_struct *tsk)
733 proc_pid_flush(proc_dentry2); 735 proc_pid_flush(proc_dentry2);
734 736
735 BUG_ON(exit_state != EXIT_ZOMBIE); 737 BUG_ON(exit_state != EXIT_ZOMBIE);
736 release_task(leader);
737 } 738 }
738 739
739 /* 740 /*
@@ -743,8 +744,11 @@ static inline int de_thread(struct task_struct *tsk)
743 sig->flags = 0; 744 sig->flags = 0;
744 745
745no_thread_group: 746no_thread_group:
746 BUG_ON(atomic_read(&sig->count) != 1);
747 exit_itimers(sig); 747 exit_itimers(sig);
748 if (leader)
749 release_task(leader);
750
751 BUG_ON(atomic_read(&sig->count) != 1);
748 752
749 if (atomic_read(&oldsighand->count) == 1) { 753 if (atomic_read(&oldsighand->count) == 1) {
750 /* 754 /*