From: Rusty Russell <rusty@rustcorp.com.au>

We can't compare waitpid() result with stop->k->tgid, since the thread will
be gone by then (thanks to Andrey Borzenkov and CONFIG_DEBUG_PAGEALLOC!



---

 kernel/kthread.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff -puN kernel/kthread.c~kthread-use-after-free-fix kernel/kthread.c
--- 25/kernel/kthread.c~kthread-use-after-free-fix	2004-02-04 22:26:45.000000000 -0800
+++ 25-akpm/kernel/kthread.c	2004-02-04 22:26:45.000000000 -0800
@@ -96,7 +96,7 @@ static void adopt_kthread(struct task_st
 static void keventd_stop_kthread(void *_stop)
 {
 	struct kthread_stop_info *stop = _stop;
-	int status;
+	int status, pid;
 	sigset_t blocked;
 	struct k_sigaction sa;
 
@@ -108,11 +108,14 @@ static void keventd_stop_kthread(void *_
 	allow_signal(SIGCHLD);
 
 	adopt_kthread(stop->k);
+	/* Grab pid now: after waitpid(), stop->k is invalid. */
+	pid = stop->k->tgid;
+
 	/* All signals are blocked, hence the force. */
 	force_sig(SIGTERM, stop->k);
 	/* Other threads might exit: if we ask for one pid that
 	 * returns -ERESTARTSYS. */
-	while (waitpid(-1, &status, __WALL) != stop->k->tgid)
+	while (waitpid(-1, &status, __WALL) != pid)
 		flush_signals(current);
 	stop->result = -((status >> 8) & 0xFF);
 	complete(&stop->done);

_