]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Add posix-cpu-timers fixes
authorChris Wright <chrisw@osdl.org>
Tue, 8 Nov 2005 23:34:23 +0000 (15:34 -0800)
committerChris Wright <chrisw@osdl.org>
Tue, 8 Nov 2005 23:34:23 +0000 (15:34 -0800)
queue/fix-de_thread-vs-send_group_sendqueue-race.patch [new file with mode: 0644]
queue/fix-signal-live-leak-in-copy_process.patch [new file with mode: 0644]
queue/series

diff --git a/queue/fix-de_thread-vs-send_group_sendqueue-race.patch b/queue/fix-de_thread-vs-send_group_sendqueue-race.patch
new file mode 100644 (file)
index 0000000..2821057
--- /dev/null
@@ -0,0 +1,73 @@
+From oleg@tv-sign.ru  Mon Nov  7 08:58:50 2005
+Date: Mon, 07 Nov 2005 21:12:43 +0300
+From: Oleg Nesterov <oleg@tv-sign.ru>
+To: paulmck@us.ibm.com, Roland McGrath <roland@redhat.com>,
+       George Anzinger <george@mvista.com>, akpm@osdl.org,
+       linux-kernel@vger.kernel.org, dipankar@in.ibm.com, mingo@elte.hu,
+       suzannew@cs.pdx.edu, Chris Wright <chrisw@osdl.org>
+Subject: [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>
+Signed-off-by: Chris Wright <chrisw@osdl.org>
+---
+
+--- 2.6.14/fs/exec.c~  2005-09-21 21:08:33.000000000 +0400
++++ 2.6.14/fs/exec.c   2005-11-07 23:54:42.000000000 +0300
+@@ -593,6 +593,7 @@ static inline int de_thread(struct task_
+       struct signal_struct *sig = tsk->signal;
+       struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
+       spinlock_t *lock = &oldsighand->siglock;
++      struct task_struct *leader = NULL;
+       int count;
+       /*
+@@ -668,7 +669,7 @@ static inline int de_thread(struct task_
+        * and to assume its PID:
+        */
+       if (!thread_group_leader(current)) {
+-              struct task_struct *leader = current->group_leader, *parent;
++              struct task_struct *parent;
+               struct dentry *proc_dentry1, *proc_dentry2;
+               unsigned long exit_state, ptrace;
+@@ -677,6 +678,7 @@ static inline int de_thread(struct task_
+                * It should already be zombie at this point, most
+                * of the time.
+                */
++              leader = current->group_leader;
+               while (leader->exit_state != EXIT_ZOMBIE)
+                       yield();
+@@ -736,7 +738,6 @@ static inline int de_thread(struct task_
+               proc_pid_flush(proc_dentry2);
+               BUG_ON(exit_state != EXIT_ZOMBIE);
+-              release_task(leader);
+         }
+       /*
+@@ -746,8 +747,11 @@ static inline int de_thread(struct task_
+       sig->flags = 0;
+ no_thread_group:
+-      BUG_ON(atomic_read(&sig->count) != 1);
+       exit_itimers(sig);
++      if (leader)
++              release_task(leader);
++
++      BUG_ON(atomic_read(&sig->count) != 1);
+       if (atomic_read(&oldsighand->count) == 1) {
+               /*
diff --git a/queue/fix-signal-live-leak-in-copy_process.patch b/queue/fix-signal-live-leak-in-copy_process.patch
new file mode 100644 (file)
index 0000000..e512b5f
--- /dev/null
@@ -0,0 +1,26 @@
+From oleg@tv-sign.ru  Sat Oct 29 08:24:41 2005
+Date: Sat, 29 Oct 2005 19:37:40 +0400
+From: Oleg Nesterov <oleg@tv-sign.ru>
+To: linux-kernel@vger.kernel.org
+Cc: Roland McGrath <roland@redhat.com>, Ingo Molnar <mingo@elte.hu>, Chris Wright <chrisw@osdl.org>, Linus Torvalds <torvalds@osdl.org>, Andrew Morton <akpm@osdl.org>
+Subject: [PATCH] fix signal->live leak in copy_process()
+
+exit_signal() (called from copy_process's error path) should decrement
+->signal->live, otherwise forking process will miss 'group_dead' in
+do_exit().
+
+Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
+Signed-off-by: Chris Wright <chrisw@osdl.org>
+---
+
+--- 2.6.14/kernel/signal.c~    2005-10-29 01:14:57.000000000 +0400
++++ 2.6.14/kernel/signal.c     2005-10-29 22:40:37.000000000 +0400
+@@ -406,6 +406,8 @@ void __exit_signal(struct task_struct *t
+ void exit_signal(struct task_struct *tsk)
+ {
++      atomic_dec(&tsk->signal->live);
++
+       write_lock_irq(&tasklist_lock);
+       __exit_signal(tsk);
+       write_unlock_irq(&tasklist_lock);
index 663fb1ec529b98692e94e9b832fd3610a46dde40..1952b25ccd69811588e4217875114d710a755d44 100644 (file)
@@ -7,3 +7,5 @@ tcp-bic-max-increment-too-large.patch
 ppc64-memory-model-depends-on-numa.patch
 airo.c-airo_cs.c-correct-prototypes.patch
 fix-zero-size-datagram-reception.patch
+fix-signal-live-leak-in-copy_process.patch
+fix-de_thread-vs-send_group_sendqueue-race.patch