From: Ingo Molnar <mingo@elte.hu>
To: Linus Torvalds <torvalds@osdl.org>, Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: [patch] fix runqueue corruption, 2.6.1-rc3-A0
Date: Thu, 8 Jan 2004 18:31:11 +0100 [thread overview]
Message-ID: <20040108173111.GA28875@elte.hu> (raw)
the attached patch fixes a nasty, few-instructions race that can result
in a corrupted runqueue at thread/process-creation time. The bug is this
code in do_fork():
p->state = TASK_STOPPED;
if (!(clone_flags & CLONE_STOPPED))
wake_up_forked_process(p); /* do this last */
when we do copy_process(), the task ends up on the tasklist and is
pid-hashed, and is thus accessible as a signal-wakeup target. But it's
in TASK_UNINTERRUPTIBLE state so wakeups cannot happen. But:
void wake_up_forked_process(task_t * p)
{
unsigned long flags;
runqueue_t *rq = task_rq_lock(current, &flags);
BUG_ON(p->state != TASK_UNINTERRUPTIBLE);
p->state = TASK_RUNNING;
so the task can be woken up from the place we do the TASK_STOPPED
change, to the task_rq_lock(). This window is very small, but not
impossible to trigger. The window is more likely to trigger on
hyperthreading systems and when CONFIG_PREEMPT is enabled. (in fact we
have a number of bugreports that i suspect are related to this race.)
The bug was introduced 6 months ago.
The effect of the bug was quite hard to debug: it results in a corrupted
runqueue due to the double list_add() - this causes lockups next time
this area of the runqueue is used, far away from the buggy code itself.
the fix is to set it to TASK_STOPPED only if we dont call
wake_up_forked_process(). (Also, to avoid this bug in the future i've
added an assert to catch illegal uses of wake_up_forked_process().)
please apply.
Ingo
--- linux/kernel/fork.c.orig
+++ linux/kernel/fork.c
@@ -1209,9 +1209,16 @@ long do_fork(unsigned long clone_flags,
set_tsk_thread_flag(p, TIF_SIGPENDING);
}
- p->state = TASK_STOPPED;
+ /*
+ * the task is in TASK_UNINTERRUPTIBLE right now, no-one
+ * can wake it up. Either wake it up as a child, which
+ * makes it TASK_RUNNING - or make it TASK_STOPPED, after
+ * which signals can wake the child up.
+ */
if (!(clone_flags & CLONE_STOPPED))
wake_up_forked_process(p); /* do this last */
+ else
+ set_task_state(p, TASK_STOPPED);
++total_forks;
if (unlikely (trace)) {
--- linux/kernel/sched.c.orig
+++ linux/kernel/sched.c
@@ -684,6 +684,7 @@ void wake_up_forked_process(task_t * p)
unsigned long flags;
runqueue_t *rq = task_rq_lock(current, &flags);
+ BUG_ON(p->state != TASK_UNINTERRUPTIBLE);
p->state = TASK_RUNNING;
/*
* We decrease the sleep average of forking parents
@@ -2832,6 +2833,7 @@ void __init sched_init(void)
rq = this_rq();
rq->curr = current;
rq->idle = current;
+ current->state = TASK_UNINTERRUPTIBLE;
set_task_cpu(current, smp_processor_id());
wake_up_forked_process(current);
next reply other threads:[~2004-01-08 17:30 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-01-08 17:31 Ingo Molnar [this message]
2004-01-08 18:53 ` [patch] fix runqueue corruption, 2.6.1-rc3-A0 Linus Torvalds
2004-01-08 19:31 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040108173111.GA28875@elte.hu \
--to=mingo@elte.hu \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.