kmod in 2.1.90

Andrew Lewycky (alewycky@globalserve.net)
Wed, 18 Mar 1998 07:53:58 -0500


kmod has a few races in it and some other dislikable behavior
(e.g. kmod_unload can wake up the wrong guy). I've tried to fix these,
and the patch follows.

Andrew Lewycky
alewycky@globalserve.net

--- kmod.c.old Wed Mar 18 07:40:14 1998
+++ kmod.c Sun Mar 15 16:45:30 1998
@@ -16,17 +16,22 @@
*/
int kmod_unload_delay = 60;
char modprobe_path[256] = "/sbin/modprobe";
-char module_name[64] = "";
-char * argv[] = { "modprobe", "-k", NULL, NULL, };
-char * envp[] = { "HOME=/", "TERM=linux", NULL, };
+static char module_name[64] = "";
+static int kmod_delete_requested = 0;
+static char * argv[] = { "modprobe", "-k", NULL, NULL, };
+static char * envp[] = { "HOME=/", "TERM=linux", NULL, };

/*
- kmod_queue synchronizes the kmod thread and the rest of the
system
+ kmod_worker is where the kmod kernel thread sleeps
+ kmod_queue is where proccesses sleep while a module is loading
+ kmod_semaphore must be grabbed by those wanting to make a
request
kmod_unload_timer is what we use to unload modules
after kmod_unload_delay seconds
*/
-struct wait_queue * kmod_queue = NULL;
-struct timer_list kmod_unload_timer;
+static struct wait_queue * kmod_worker = NULL;
+static struct wait_queue * kmod_queue = NULL;
+static struct semaphore kmod_semaphore = MUTEX_LOCKED;
+static struct timer_list kmod_unload_timer;

/*
kmod_thread is the thread that does most of the work.
kmod_unload and
@@ -34,8 +39,6 @@
*/
int kmod_thread(void * data)
{
- int pid;
-
/*
Initialize basic thread information
*/
@@ -50,7 +53,7 @@
*/

while (1) {
- interruptible_sleep_on(&kmod_queue);
+ interruptible_sleep_on(&kmod_worker);

/*
If request_module woke us up, we should try to
@@ -59,10 +62,8 @@
(if somehow both want us to do something, ignore
the
delete_module request)
*/
- if (module_name[0] == '\0') {
- delete_module(NULL);
- } else {
- pid = fork();
+ if (module_name[0] != '\0') {
+ pid_t pid = fork();
if (pid > 0) {
waitpid(pid, NULL, 0);
module_name[0] = '\0';
@@ -83,6 +84,11 @@
printk("error, fork failed in kmod\n");
}
}
+
+ if (kmod_delete_requested) {
+ kmod_delete_requested = 0;
+ delete_module(NULL);
+ }
}

return 0; /* Never reached. */
@@ -100,7 +106,8 @@
we are in the bottom half of the kernel (right?))
once it is awake, reset the timer
*/
- wake_up(&kmod_queue);
+ kmod_delete_requested = 1;
+ wake_up(&kmod_worker);
kmod_unload_timer.expires = jiffies + (kmod_unload_delay * HZ);
add_timer(&kmod_unload_timer);
}
@@ -118,6 +125,8 @@
kmod_unload_timer.function = kmod_unload;
add_timer(&kmod_unload_timer);

+ up(&kmod_semaphore);
+
return 0;
}

@@ -127,6 +136,8 @@
*/
int request_module(const char * name)
{
+ down(&kmod_semaphore);
+
/* first, copy the name of the module into module_name */
/* then wake_up() the kmod daemon */
/* wait for the kmod daemon to finish (it will wake us up) */
@@ -136,8 +147,10 @@
the module into module_name. Once that is done, wake up
kmod_thread.
*/
- strcpy(module_name, name);
- wake_up(&kmod_queue);
+ strncpy(module_name, name, sizeof(module_name)-1);
+ module_name[sizeof(module_name)-1] = '\0';
+
+ wake_up(&kmod_worker);

/*
Now that we have told kmod_thread what to do, we want to

@@ -127,6 +136,8 @@
*/
int request_module(const char * name)
{
+ down(&kmod_semaphore);
+
/* first, copy the name of the module into module_name */
/* then wake_up() the kmod daemon */
/* wait for the kmod daemon to finish (it will wake us up) */
@@ -136,8 +147,10 @@
the module into module_name. Once that is done, wake up
kmod_thread.
*/
- strcpy(module_name, name);
- wake_up(&kmod_queue);
+ strncpy(module_name, name, sizeof(module_name)-1);
+ module_name[sizeof(module_name)-1] = '\0';
+
+ wake_up(&kmod_worker);

/*
Now that we have told kmod_thread what to do, we want to
@@ -145,5 +158,7 @@
at which point we will be done (the module will be
loaded).
*/
interruptible_sleep_on(&kmod_queue);
+
+ up(&kmod_semaphore);
return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu