All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nick Piggin <nickpiggin@yahoo.com.au>
To: Andrew Morton <akpm@osdl.org>
Cc: bstroesser@fujitsu-siemens.com, roland@redhat.com,
	jdike@addtoit.com, blaisorblade_spam@yahoo.it,
	user-mode-linux-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org, Ingo Molnar <mingo@elte.hu>
Subject: [uml-devel] [PATCH] fix wait_task_inactive race (was Re: Race condition in ptrace)
Date: Sun, 06 Feb 2005 14:26:10 +1100	[thread overview]
Message-ID: <42058E52.8030306@yahoo.com.au> (raw)
In-Reply-To: <42044D17.5040703@yahoo.com.au>

[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]

Nick Piggin wrote:

> Something like the following (untested) extension of Bodo's work
> could be the minimal fix for 2.6.11. As I've said though, I'd
> consider it a hack and prefer to do something about the locking.
> That could be done after 2.6.11 though. Depends how you feel.
> 

I think this is the right fix.

When a task is put to sleep, it is dequeued from the runqueue
while it is still running. The problem is that the runqueue
lock can be dropped and retaken in schedule() before the task
actually schedules off, and wait_task_inactive did not account
for this.

I introduced a new function to resolve this state, fixed
wait_task_inactive, and converted over an open coded test.

I did a quick audit of sched.c, and nothing else seems to have
made the same mistake.

Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>


Question: why does wait_task_inactive have different semantics
for UP && PREEMPT than SMP && PREEMPT? I can see that the kthread
caler probably isn't used in the UP case, but technically it is
relying on behaviour that it doesn't get with UP and PREEMPT.
Looks like the ptrace.c caller won't care.

But still, can we either fix it or put a nice comment there?
Preferably fix, if this isn't a very performance critical path?


[-- Attachment #2: sched-fixup-races.patch --]
[-- Type: text/plain, Size: 1416 bytes --]




---

 linux-2.6-npiggin/kernel/sched.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff -puN kernel/sched.c~sched-fixup-races kernel/sched.c
--- linux-2.6/kernel/sched.c~sched-fixup-races	2005-02-06 14:03:53.000000000 +1100
+++ linux-2.6-npiggin/kernel/sched.c	2005-02-06 14:06:43.000000000 +1100
@@ -298,6 +298,14 @@ static DEFINE_PER_CPU(struct runqueue, r
 #endif
 
 /*
+ * Is the task currently running or on the runqueue
+ */
+static int task_onqueue(runqueue_t *rq, task_t *p)
+{
+	return (p->array || task_running(rq, p));
+}
+
+/*
  * task_rq_lock - lock the runqueue a given task resides on and disable
  * interrupts.  Note the ordering: we can safely lookup the task_rq without
  * explicitly disabling preemption.
@@ -836,7 +844,7 @@ static int migrate_task(task_t *p, int d
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->array && !task_running(rq, p)) {
+	if (!task_onqueue(rq, p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -867,7 +875,7 @@ void wait_task_inactive(task_t * p)
 repeat:
 	rq = task_rq_lock(p, &flags);
 	/* Must be off runqueue entirely, not preempted. */
-	if (unlikely(p->array)) {
+	if (unlikely(task_onqueue(rq, p))) {
 		/* If it's preempted, we yield.  It could be a while. */
 		preempted = !task_running(rq, p);
 		task_rq_unlock(rq, &flags);

_

WARNING: multiple messages have this Message-ID (diff)
From: Nick Piggin <nickpiggin@yahoo.com.au>
To: Andrew Morton <akpm@osdl.org>
Cc: bstroesser@fujitsu-siemens.com, roland@redhat.com,
	jdike@addtoit.com, blaisorblade_spam@yahoo.it,
	user-mode-linux-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org, Ingo Molnar <mingo@elte.hu>
Subject: [PATCH] fix wait_task_inactive race (was Re: Race condition in ptrace)
Date: Sun, 06 Feb 2005 14:26:10 +1100	[thread overview]
Message-ID: <42058E52.8030306@yahoo.com.au> (raw)
In-Reply-To: <42044D17.5040703@yahoo.com.au>

[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]

Nick Piggin wrote:

> Something like the following (untested) extension of Bodo's work
> could be the minimal fix for 2.6.11. As I've said though, I'd
> consider it a hack and prefer to do something about the locking.
> That could be done after 2.6.11 though. Depends how you feel.
> 

I think this is the right fix.

When a task is put to sleep, it is dequeued from the runqueue
while it is still running. The problem is that the runqueue
lock can be dropped and retaken in schedule() before the task
actually schedules off, and wait_task_inactive did not account
for this.

I introduced a new function to resolve this state, fixed
wait_task_inactive, and converted over an open coded test.

I did a quick audit of sched.c, and nothing else seems to have
made the same mistake.

Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>


Question: why does wait_task_inactive have different semantics
for UP && PREEMPT than SMP && PREEMPT? I can see that the kthread
caler probably isn't used in the UP case, but technically it is
relying on behaviour that it doesn't get with UP and PREEMPT.
Looks like the ptrace.c caller won't care.

But still, can we either fix it or put a nice comment there?
Preferably fix, if this isn't a very performance critical path?


[-- Attachment #2: sched-fixup-races.patch --]
[-- Type: text/plain, Size: 1416 bytes --]




---

 linux-2.6-npiggin/kernel/sched.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff -puN kernel/sched.c~sched-fixup-races kernel/sched.c
--- linux-2.6/kernel/sched.c~sched-fixup-races	2005-02-06 14:03:53.000000000 +1100
+++ linux-2.6-npiggin/kernel/sched.c	2005-02-06 14:06:43.000000000 +1100
@@ -298,6 +298,14 @@ static DEFINE_PER_CPU(struct runqueue, r
 #endif
 
 /*
+ * Is the task currently running or on the runqueue
+ */
+static int task_onqueue(runqueue_t *rq, task_t *p)
+{
+	return (p->array || task_running(rq, p));
+}
+
+/*
  * task_rq_lock - lock the runqueue a given task resides on and disable
  * interrupts.  Note the ordering: we can safely lookup the task_rq without
  * explicitly disabling preemption.
@@ -836,7 +844,7 @@ static int migrate_task(task_t *p, int d
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->array && !task_running(rq, p)) {
+	if (!task_onqueue(rq, p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -867,7 +875,7 @@ void wait_task_inactive(task_t * p)
 repeat:
 	rq = task_rq_lock(p, &flags);
 	/* Must be off runqueue entirely, not preempted. */
-	if (unlikely(p->array)) {
+	if (unlikely(task_onqueue(rq, p))) {
 		/* If it's preempted, we yield.  It could be a while. */
 		preempted = !task_running(rq, p);
 		task_rq_unlock(rq, &flags);

_

  reply	other threads:[~2005-02-06  3:26 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-02-03 12:51 [uml-devel] Race condition in ptrace Bodo Stroesser
2005-02-03 12:51 ` Bodo Stroesser
2005-02-04  0:27 ` [uml-devel] " Nick Piggin
2005-02-04  0:27   ` Nick Piggin
2005-02-04 12:35   ` [uml-devel] " Bodo Stroesser
2005-02-04 12:35     ` Bodo Stroesser
2005-02-04 22:15     ` [uml-devel] " Nick Piggin
2005-02-04 22:15       ` Nick Piggin
2005-02-04 22:39       ` [uml-devel] " Andrew Morton
2005-02-04 22:39         ` Andrew Morton
2005-02-04 23:15         ` [uml-devel] " Nick Piggin
2005-02-04 23:15           ` Nick Piggin
2005-02-05  4:35           ` [uml-devel] " Nick Piggin
2005-02-05  4:35             ` Nick Piggin
2005-02-06  3:26             ` Nick Piggin [this message]
2005-02-06  3:26               ` [PATCH] fix wait_task_inactive race (was Re: Race condition in ptrace) Nick Piggin
2005-02-06  7:19               ` [uml-devel] " Ingo Molnar
2005-02-06  7:19                 ` Ingo Molnar
2005-02-06  7:36                 ` [uml-devel] " Nick Piggin
2005-02-06  7:36                   ` Nick Piggin
2005-02-06  7:47                   ` [uml-devel] " Nick Piggin
2005-02-06  7:47                     ` Nick Piggin
2005-02-14 16:07                   ` [uml-devel] " Bodo Stroesser
2005-02-14 16:07                     ` Bodo Stroesser

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=42058E52.8030306@yahoo.com.au \
    --to=nickpiggin@yahoo.com.au \
    --cc=akpm@osdl.org \
    --cc=blaisorblade_spam@yahoo.it \
    --cc=bstroesser@fujitsu-siemens.com \
    --cc=jdike@addtoit.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=roland@redhat.com \
    --cc=user-mode-linux-devel@lists.sourceforge.net \
    /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.