[PATCH] kernel_thread race

Jeff Dike (jdike@karaya.com)
Thu, 26 Aug 1999 14:30:19 -0400


kswapd_init does this:
kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);

kswapd does this:
struct task_struct *tsk = current;
kswapd_process = tsk;

However, if try_to_free_pages runs before kswapd, then it will do this:
wake_up_process(kswapd_process)
with kswapd_process == NULL which causes NULL dereferences in wake_up_process.

The fix implemented in the patch below changes kernel_thread to return a
task_struct instead of a pid. kswapd_process and bdflush_tsk get initialized
in kswapd_init and bdflush_init, respectively, rather than in the new thread.

The two kernel_thread calls which look at the pid change from
pid = kernel_thread(...);
to
pid = kernel_thread(...)->pid;

Jeff
diff -Naur -X ../exclude-files orig/fs/buffer.c um/fs/buffer.c
--- orig/fs/buffer.c Thu Aug 26 01:32:33 1999
+++ um/fs/buffer.c Thu Aug 26 13:16:27 1999
@@ -2392,7 +2392,6 @@
current->session = 1;
current->pgrp = 1;
sprintf(current->comm, "kflushd");
- bdflush_tsk = current;

for (;;) {
int nlist;
@@ -2472,7 +2471,8 @@

static int __init bdflush_init(void)
{
- kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ bdflush_tsk = kernel_thread(bdflush, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
return 0;
}

diff -Naur -X ../exclude-files orig/init/main.c um/init/main.c
--- orig/init/main.c Thu Aug 26 00:30:18 1999
+++ um/init/main.c Thu Aug 26 13:17:16 1999
@@ -666,7 +667,7 @@
int error;
int i, pid;

- pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
+ pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD)->pid;
if (pid>0)
while (pid != wait(&i));
if (MAJOR(real_root_dev) != RAMDISK_MAJOR
diff -Naur -X ../exclude-files orig/kernel/kmod.c um/kernel/kmod.c
--- orig/kernel/kmod.c Thu Nov 12 12:58:32 1998
+++ um/kernel/kmod.c Thu Aug 26 13:17:33 1999
@@ -104,7 +104,7 @@
return -EPERM;
}

- pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
+ pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS)->pid;
if (pid < 0) {
printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name,
-pid);
return pid;
diff -Naur -X ../exclude-files orig/mm/vmscan.c um/mm/vmscan.c
--- orig/mm/vmscan.c Thu Aug 26 00:30:19 1999
+++ um/mm/vmscan.c Thu Aug 26 13:16:55 1999
@@ -454,7 +454,6 @@
{
struct task_struct *tsk = current;

- kswapd_process = tsk;
tsk->session = 1;
tsk->pgrp = 1;
strcpy(tsk->comm, "kswapd");
@@ -525,7 +524,8 @@
{
printk("Starting kswapd v1.6\n");
swap_setup();
- kernel_thread(kswapd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ kswapd_process = kernel_thread(kswapd, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/