aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-01-29 17:13:21 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-01-29 01:13:22 -0500
commitbb9d3d56e792d2619cc0903df4ac01d86ac1261d (patch)
tree25ff54c8402b6dedf45a3145b5d9904e14983bf4 /kernel/module.c
parentefa5345e39d01deef349c120f55ac6b6eabe7457 (diff)
module: better OOPS and lockdep coverage for loading modules
If we put the module in the linked list *before* calling into to, we get the module name and functions in the OOPS (is_module_address can find the module). It also helps lockdep in a similar way. Acked-and-tested-by: Joern Engel <joern@lazybastard.org> Tested-by: Erez Zadok <ezk@cs.sunysb.edu> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 276abd7b7ff7..12067ff34d01 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1294,6 +1294,17 @@ static void mod_kobject_remove(struct module *mod)
1294} 1294}
1295 1295
1296/* 1296/*
1297 * link the module with the whole machine is stopped with interrupts off
1298 * - this defends against kallsyms not taking locks
1299 */
1300static int __link_module(void *_mod)
1301{
1302 struct module *mod = _mod;
1303 list_add(&mod->list, &modules);
1304 return 0;
1305}
1306
1307/*
1297 * unlink the module with the whole machine is stopped with interrupts off 1308 * unlink the module with the whole machine is stopped with interrupts off
1298 * - this defends against kallsyms not taking locks 1309 * - this defends against kallsyms not taking locks
1299 */ 1310 */
@@ -2035,6 +2046,11 @@ static struct module *load_module(void __user *umod,
2035 printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", 2046 printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
2036 mod->name); 2047 mod->name);
2037 2048
2049 /* Now sew it into the lists so we can get lockdep and oops
2050 * info during argument parsing. Noone should access us, since
2051 * strong_try_module_get() will fail. */
2052 stop_machine_run(__link_module, mod, NR_CPUS);
2053
2038 /* Size of section 0 is 0, so this works well if no params */ 2054 /* Size of section 0 is 0, so this works well if no params */
2039 err = parse_args(mod->name, mod->args, 2055 err = parse_args(mod->name, mod->args,
2040 (struct kernel_param *) 2056 (struct kernel_param *)
@@ -2043,7 +2059,7 @@ static struct module *load_module(void __user *umod,
2043 / sizeof(struct kernel_param), 2059 / sizeof(struct kernel_param),
2044 NULL); 2060 NULL);
2045 if (err < 0) 2061 if (err < 0)
2046 goto arch_cleanup; 2062 goto unlink;
2047 2063
2048 err = mod_sysfs_setup(mod, 2064 err = mod_sysfs_setup(mod,
2049 (struct kernel_param *) 2065 (struct kernel_param *)
@@ -2051,7 +2067,7 @@ static struct module *load_module(void __user *umod,
2051 sechdrs[setupindex].sh_size 2067 sechdrs[setupindex].sh_size
2052 / sizeof(struct kernel_param)); 2068 / sizeof(struct kernel_param));
2053 if (err < 0) 2069 if (err < 0)
2054 goto arch_cleanup; 2070 goto unlink;
2055 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2071 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
2056 add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2072 add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
2057 2073
@@ -2066,7 +2082,8 @@ static struct module *load_module(void __user *umod,
2066 /* Done! */ 2082 /* Done! */
2067 return mod; 2083 return mod;
2068 2084
2069 arch_cleanup: 2085 unlink:
2086 stop_machine_run(__unlink_module, mod, NR_CPUS);
2070 module_arch_cleanup(mod); 2087 module_arch_cleanup(mod);
2071 cleanup: 2088 cleanup:
2072 kobject_del(&mod->mkobj.kobj); 2089 kobject_del(&mod->mkobj.kobj);
@@ -2091,17 +2108,6 @@ static struct module *load_module(void __user *umod,
2091 goto free_hdr; 2108 goto free_hdr;
2092} 2109}
2093 2110
2094/*
2095 * link the module with the whole machine is stopped with interrupts off
2096 * - this defends against kallsyms not taking locks
2097 */
2098static int __link_module(void *_mod)
2099{
2100 struct module *mod = _mod;
2101 list_add(&mod->list, &modules);
2102 return 0;
2103}
2104
2105/* This is where the real work happens */ 2111/* This is where the real work happens */
2106asmlinkage long 2112asmlinkage long
2107sys_init_module(void __user *umod, 2113sys_init_module(void __user *umod,
@@ -2126,10 +2132,6 @@ sys_init_module(void __user *umod,
2126 return PTR_ERR(mod); 2132 return PTR_ERR(mod);
2127 } 2133 }
2128 2134
2129 /* Now sew it into the lists. They won't access us, since
2130 strong_try_module_get() will fail. */
2131 stop_machine_run(__link_module, mod, NR_CPUS);
2132
2133 /* Drop lock so they can recurse */ 2135 /* Drop lock so they can recurse */
2134 mutex_unlock(&module_mutex); 2136 mutex_unlock(&module_mutex);
2135 2137