diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-29 17:13:21 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-29 01:13:22 -0500 |
commit | bb9d3d56e792d2619cc0903df4ac01d86ac1261d (patch) | |
tree | 25ff54c8402b6dedf45a3145b5d9904e14983bf4 | |
parent | efa5345e39d01deef349c120f55ac6b6eabe7457 (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>
-rw-r--r-- | kernel/module.c | 38 |
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 | */ | ||
1300 | static 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 | */ | ||
2098 | static 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 */ |
2106 | asmlinkage long | 2112 | asmlinkage long |
2107 | sys_init_module(void __user *umod, | 2113 | sys_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 | ||