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 /kernel/module.c | |
| 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>
Diffstat (limited to 'kernel/module.c')
| -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 276abd7b7f..12067ff34d 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 | ||
