patch-2.4.2 linux/kernel/module.c
Next file: linux/kernel/printk.c
Previous file: linux/kernel/ksyms.c
Back to the patch index
Back to the overall index
- Lines: 98
- Date:
Fri Feb 16 16:02:37 2001
- Orig file:
v2.4.1/linux/kernel/module.c
- Orig date:
Mon Nov 27 17:38:07 2000
diff -u --recursive --new-file v2.4.1/linux/kernel/module.c linux/kernel/module.c
@@ -23,6 +23,7 @@
* Fix sys_init_module race, Andrew Morton <andrewm@uow.edu.au> Oct 2000
* http://www.uwsg.iu.edu/hypermail/linux/kernel/0008.3/0379.html
* Replace xxx_module_symbol with inter_module_xxx. Keith Owens <kaos@ocs.com.au> Oct 2000
+ * Add a module list lock for kernel fault race fixing. Alan Cox <alan@redhat.com>
*
* This source is covered by the GNU GPL, the same as all kernel sources.
*/
@@ -65,6 +66,17 @@
static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
static int kmalloc_failed;
+/*
+ * This lock prevents modifications that might race the kernel fault
+ * fixups. It does not prevent reader walks that the modules code
+ * does. The kernel lock does that.
+ *
+ * Since vmalloc fault fixups occur in any context this lock is taken
+ * irqsave at all times.
+ */
+
+spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
+
/**
* inter_module_register - register a new set of inter module data.
* @im_name: an arbitrary string to identify the data, must be unique
@@ -283,6 +295,7 @@
char *name;
long namelen, error;
struct module *mod;
+ unsigned long flags;
if (!capable(CAP_SYS_MODULE))
return -EPERM;
@@ -306,14 +319,16 @@
memset(mod, 0, sizeof(*mod));
mod->size_of_struct = sizeof(*mod);
- mod->next = module_list;
mod->name = (char *)(mod + 1);
mod->size = size;
memcpy((char*)(mod+1), name, namelen+1);
put_mod_name(name);
+ spin_lock_irqsave(&modlist_lock, flags);
+ mod->next = module_list;
module_list = mod; /* link it in */
+ spin_unlock_irqrestore(&modlist_lock, flags);
error = (long) mod;
goto err0;
@@ -628,6 +643,7 @@
/* Do automatic reaping */
restart:
something_changed = 0;
+
for (mod = module_list; mod != &kernel_module; mod = next) {
next = mod->next;
spin_lock(&unload_lock);
@@ -651,10 +667,13 @@
spin_unlock(&unload_lock);
}
}
+
if (something_changed)
goto restart;
+
for (mod = module_list; mod != &kernel_module; mod = mod->next)
mod->flags &= ~MOD_JUST_FREED;
+
error = 0;
out:
unlock_kernel();
@@ -1018,6 +1037,7 @@
{
struct module_ref *dep;
unsigned i;
+ unsigned long flags;
/* Let the module clean up. */
@@ -1041,6 +1061,7 @@
/* And from the main module list. */
+ spin_lock_irqsave(&modlist_lock, flags);
if (mod == module_list) {
module_list = mod->next;
} else {
@@ -1049,6 +1070,7 @@
continue;
p->next = mod->next;
}
+ spin_unlock_irqrestore(&modlist_lock, flags);
/* And free the memory. */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)