diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/extable.c | 3 | ||||
-rw-r--r-- | kernel/kallsyms.c | 11 | ||||
-rw-r--r-- | kernel/module.c | 102 | ||||
-rw-r--r-- | kernel/params.c | 8 |
4 files changed, 77 insertions, 47 deletions
diff --git a/kernel/extable.c b/kernel/extable.c index 7fe262855317..a26cb2e17023 100644 --- a/kernel/extable.c +++ b/kernel/extable.c | |||
@@ -46,7 +46,8 @@ int core_kernel_text(unsigned long addr) | |||
46 | addr <= (unsigned long)_etext) | 46 | addr <= (unsigned long)_etext) |
47 | return 1; | 47 | return 1; |
48 | 48 | ||
49 | if (addr >= (unsigned long)_sinittext && | 49 | if (system_state == SYSTEM_BOOTING && |
50 | addr >= (unsigned long)_sinittext && | ||
50 | addr <= (unsigned long)_einittext) | 51 | addr <= (unsigned long)_einittext) |
51 | return 1; | 52 | return 1; |
52 | return 0; | 53 | return 0; |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 2fc25810509e..7dadc71ce516 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -233,10 +233,11 @@ static unsigned long get_symbol_pos(unsigned long addr, | |||
233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, | 233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, |
234 | unsigned long *offset) | 234 | unsigned long *offset) |
235 | { | 235 | { |
236 | char namebuf[KSYM_NAME_LEN]; | ||
236 | if (is_ksym_addr(addr)) | 237 | if (is_ksym_addr(addr)) |
237 | return !!get_symbol_pos(addr, symbolsize, offset); | 238 | return !!get_symbol_pos(addr, symbolsize, offset); |
238 | 239 | ||
239 | return !!module_address_lookup(addr, symbolsize, offset, NULL); | 240 | return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf); |
240 | } | 241 | } |
241 | 242 | ||
242 | /* | 243 | /* |
@@ -251,8 +252,6 @@ const char *kallsyms_lookup(unsigned long addr, | |||
251 | unsigned long *offset, | 252 | unsigned long *offset, |
252 | char **modname, char *namebuf) | 253 | char **modname, char *namebuf) |
253 | { | 254 | { |
254 | const char *msym; | ||
255 | |||
256 | namebuf[KSYM_NAME_LEN - 1] = 0; | 255 | namebuf[KSYM_NAME_LEN - 1] = 0; |
257 | namebuf[0] = 0; | 256 | namebuf[0] = 0; |
258 | 257 | ||
@@ -268,10 +267,8 @@ const char *kallsyms_lookup(unsigned long addr, | |||
268 | } | 267 | } |
269 | 268 | ||
270 | /* see if it's in a module */ | 269 | /* see if it's in a module */ |
271 | msym = module_address_lookup(addr, symbolsize, offset, modname); | 270 | return module_address_lookup(addr, symbolsize, offset, modname, |
272 | if (msym) | 271 | namebuf); |
273 | return strncpy(namebuf, msym, KSYM_NAME_LEN - 1); | ||
274 | |||
275 | return NULL; | 272 | return NULL; |
276 | } | 273 | } |
277 | 274 | ||
diff --git a/kernel/module.c b/kernel/module.c index 1bb4c5e0d56e..f6a4e721fd49 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -65,6 +65,9 @@ | |||
65 | static DEFINE_MUTEX(module_mutex); | 65 | static DEFINE_MUTEX(module_mutex); |
66 | static LIST_HEAD(modules); | 66 | static LIST_HEAD(modules); |
67 | 67 | ||
68 | /* Waiting for a module to finish initializing? */ | ||
69 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); | ||
70 | |||
68 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 71 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
69 | 72 | ||
70 | int register_module_notifier(struct notifier_block * nb) | 73 | int register_module_notifier(struct notifier_block * nb) |
@@ -84,8 +87,11 @@ EXPORT_SYMBOL(unregister_module_notifier); | |||
84 | static inline int strong_try_module_get(struct module *mod) | 87 | static inline int strong_try_module_get(struct module *mod) |
85 | { | 88 | { |
86 | if (mod && mod->state == MODULE_STATE_COMING) | 89 | if (mod && mod->state == MODULE_STATE_COMING) |
90 | return -EBUSY; | ||
91 | if (try_module_get(mod)) | ||
87 | return 0; | 92 | return 0; |
88 | return try_module_get(mod); | 93 | else |
94 | return -ENOENT; | ||
89 | } | 95 | } |
90 | 96 | ||
91 | static inline void add_taint_module(struct module *mod, unsigned flag) | 97 | static inline void add_taint_module(struct module *mod, unsigned flag) |
@@ -539,11 +545,21 @@ static int already_uses(struct module *a, struct module *b) | |||
539 | static int use_module(struct module *a, struct module *b) | 545 | static int use_module(struct module *a, struct module *b) |
540 | { | 546 | { |
541 | struct module_use *use; | 547 | struct module_use *use; |
542 | int no_warn; | 548 | int no_warn, err; |
543 | 549 | ||
544 | if (b == NULL || already_uses(a, b)) return 1; | 550 | if (b == NULL || already_uses(a, b)) return 1; |
545 | 551 | ||
546 | if (!strong_try_module_get(b)) | 552 | /* If we're interrupted or time out, we fail. */ |
553 | if (wait_event_interruptible_timeout( | ||
554 | module_wq, (err = strong_try_module_get(b)) != -EBUSY, | ||
555 | 30 * HZ) <= 0) { | ||
556 | printk("%s: gave up waiting for init of module %s.\n", | ||
557 | a->name, b->name); | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | /* If strong_try_module_get() returned a different error, we fail. */ | ||
562 | if (err) | ||
547 | return 0; | 563 | return 0; |
548 | 564 | ||
549 | DEBUGP("Allocating new usage for %s.\n", a->name); | 565 | DEBUGP("Allocating new usage for %s.\n", a->name); |
@@ -722,7 +738,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
722 | mutex_lock(&module_mutex); | 738 | mutex_lock(&module_mutex); |
723 | } | 739 | } |
724 | /* Store the name of the last unloaded module for diagnostic purposes */ | 740 | /* Store the name of the last unloaded module for diagnostic purposes */ |
725 | sprintf(last_unloaded_module, mod->name); | 741 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
726 | free_module(mod); | 742 | free_module(mod); |
727 | 743 | ||
728 | out: | 744 | out: |
@@ -816,7 +832,7 @@ static inline void module_unload_free(struct module *mod) | |||
816 | 832 | ||
817 | static inline int use_module(struct module *a, struct module *b) | 833 | static inline int use_module(struct module *a, struct module *b) |
818 | { | 834 | { |
819 | return strong_try_module_get(b); | 835 | return strong_try_module_get(b) == 0; |
820 | } | 836 | } |
821 | 837 | ||
822 | static inline void module_unload_init(struct module *mod) | 838 | static inline void module_unload_init(struct module *mod) |
@@ -1214,6 +1230,7 @@ void module_remove_modinfo_attrs(struct module *mod) | |||
1214 | int mod_sysfs_init(struct module *mod) | 1230 | int mod_sysfs_init(struct module *mod) |
1215 | { | 1231 | { |
1216 | int err; | 1232 | int err; |
1233 | struct kobject *kobj; | ||
1217 | 1234 | ||
1218 | if (!module_sysfs_initialized) { | 1235 | if (!module_sysfs_initialized) { |
1219 | printk(KERN_ERR "%s: module sysfs not initialized\n", | 1236 | printk(KERN_ERR "%s: module sysfs not initialized\n", |
@@ -1221,6 +1238,15 @@ int mod_sysfs_init(struct module *mod) | |||
1221 | err = -EINVAL; | 1238 | err = -EINVAL; |
1222 | goto out; | 1239 | goto out; |
1223 | } | 1240 | } |
1241 | |||
1242 | kobj = kset_find_obj(module_kset, mod->name); | ||
1243 | if (kobj) { | ||
1244 | printk(KERN_ERR "%s: module is already loaded\n", mod->name); | ||
1245 | kobject_put(kobj); | ||
1246 | err = -EINVAL; | ||
1247 | goto out; | ||
1248 | } | ||
1249 | |||
1224 | mod->mkobj.mod = mod; | 1250 | mod->mkobj.mod = mod; |
1225 | 1251 | ||
1226 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); | 1252 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); |
@@ -1278,6 +1304,17 @@ static void mod_kobject_remove(struct module *mod) | |||
1278 | } | 1304 | } |
1279 | 1305 | ||
1280 | /* | 1306 | /* |
1307 | * link the module with the whole machine is stopped with interrupts off | ||
1308 | * - this defends against kallsyms not taking locks | ||
1309 | */ | ||
1310 | static int __link_module(void *_mod) | ||
1311 | { | ||
1312 | struct module *mod = _mod; | ||
1313 | list_add(&mod->list, &modules); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1281 | * unlink the module with the whole machine is stopped with interrupts off | 1318 | * unlink the module with the whole machine is stopped with interrupts off |
1282 | * - this defends against kallsyms not taking locks | 1319 | * - this defends against kallsyms not taking locks |
1283 | */ | 1320 | */ |
@@ -1326,7 +1363,7 @@ void *__symbol_get(const char *symbol) | |||
1326 | 1363 | ||
1327 | preempt_disable(); | 1364 | preempt_disable(); |
1328 | value = __find_symbol(symbol, &owner, &crc, 1); | 1365 | value = __find_symbol(symbol, &owner, &crc, 1); |
1329 | if (value && !strong_try_module_get(owner)) | 1366 | if (value && strong_try_module_get(owner) != 0) |
1330 | value = 0; | 1367 | value = 0; |
1331 | preempt_enable(); | 1368 | preempt_enable(); |
1332 | 1369 | ||
@@ -1889,7 +1926,7 @@ static struct module *load_module(void __user *umod, | |||
1889 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 1926 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
1890 | 1927 | ||
1891 | if (strcmp(mod->name, "ndiswrapper") == 0) | 1928 | if (strcmp(mod->name, "ndiswrapper") == 0) |
1892 | add_taint(TAINT_PROPRIETARY_MODULE); | 1929 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1893 | if (strcmp(mod->name, "driverloader") == 0) | 1930 | if (strcmp(mod->name, "driverloader") == 0) |
1894 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | 1931 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1895 | 1932 | ||
@@ -2019,6 +2056,11 @@ static struct module *load_module(void __user *umod, | |||
2019 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | 2056 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", |
2020 | mod->name); | 2057 | mod->name); |
2021 | 2058 | ||
2059 | /* Now sew it into the lists so we can get lockdep and oops | ||
2060 | * info during argument parsing. Noone should access us, since | ||
2061 | * strong_try_module_get() will fail. */ | ||
2062 | stop_machine_run(__link_module, mod, NR_CPUS); | ||
2063 | |||
2022 | /* Size of section 0 is 0, so this works well if no params */ | 2064 | /* Size of section 0 is 0, so this works well if no params */ |
2023 | err = parse_args(mod->name, mod->args, | 2065 | err = parse_args(mod->name, mod->args, |
2024 | (struct kernel_param *) | 2066 | (struct kernel_param *) |
@@ -2027,7 +2069,7 @@ static struct module *load_module(void __user *umod, | |||
2027 | / sizeof(struct kernel_param), | 2069 | / sizeof(struct kernel_param), |
2028 | NULL); | 2070 | NULL); |
2029 | if (err < 0) | 2071 | if (err < 0) |
2030 | goto arch_cleanup; | 2072 | goto unlink; |
2031 | 2073 | ||
2032 | err = mod_sysfs_setup(mod, | 2074 | err = mod_sysfs_setup(mod, |
2033 | (struct kernel_param *) | 2075 | (struct kernel_param *) |
@@ -2035,7 +2077,7 @@ static struct module *load_module(void __user *umod, | |||
2035 | sechdrs[setupindex].sh_size | 2077 | sechdrs[setupindex].sh_size |
2036 | / sizeof(struct kernel_param)); | 2078 | / sizeof(struct kernel_param)); |
2037 | if (err < 0) | 2079 | if (err < 0) |
2038 | goto arch_cleanup; | 2080 | goto unlink; |
2039 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2081 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
2040 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2082 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
2041 | 2083 | ||
@@ -2050,7 +2092,8 @@ static struct module *load_module(void __user *umod, | |||
2050 | /* Done! */ | 2092 | /* Done! */ |
2051 | return mod; | 2093 | return mod; |
2052 | 2094 | ||
2053 | arch_cleanup: | 2095 | unlink: |
2096 | stop_machine_run(__unlink_module, mod, NR_CPUS); | ||
2054 | module_arch_cleanup(mod); | 2097 | module_arch_cleanup(mod); |
2055 | cleanup: | 2098 | cleanup: |
2056 | kobject_del(&mod->mkobj.kobj); | 2099 | kobject_del(&mod->mkobj.kobj); |
@@ -2075,17 +2118,6 @@ static struct module *load_module(void __user *umod, | |||
2075 | goto free_hdr; | 2118 | goto free_hdr; |
2076 | } | 2119 | } |
2077 | 2120 | ||
2078 | /* | ||
2079 | * link the module with the whole machine is stopped with interrupts off | ||
2080 | * - this defends against kallsyms not taking locks | ||
2081 | */ | ||
2082 | static int __link_module(void *_mod) | ||
2083 | { | ||
2084 | struct module *mod = _mod; | ||
2085 | list_add(&mod->list, &modules); | ||
2086 | return 0; | ||
2087 | } | ||
2088 | |||
2089 | /* This is where the real work happens */ | 2121 | /* This is where the real work happens */ |
2090 | asmlinkage long | 2122 | asmlinkage long |
2091 | sys_init_module(void __user *umod, | 2123 | sys_init_module(void __user *umod, |
@@ -2110,10 +2142,6 @@ sys_init_module(void __user *umod, | |||
2110 | return PTR_ERR(mod); | 2142 | return PTR_ERR(mod); |
2111 | } | 2143 | } |
2112 | 2144 | ||
2113 | /* Now sew it into the lists. They won't access us, since | ||
2114 | strong_try_module_get() will fail. */ | ||
2115 | stop_machine_run(__link_module, mod, NR_CPUS); | ||
2116 | |||
2117 | /* Drop lock so they can recurse */ | 2145 | /* Drop lock so they can recurse */ |
2118 | mutex_unlock(&module_mutex); | 2146 | mutex_unlock(&module_mutex); |
2119 | 2147 | ||
@@ -2132,6 +2160,7 @@ sys_init_module(void __user *umod, | |||
2132 | mutex_lock(&module_mutex); | 2160 | mutex_lock(&module_mutex); |
2133 | free_module(mod); | 2161 | free_module(mod); |
2134 | mutex_unlock(&module_mutex); | 2162 | mutex_unlock(&module_mutex); |
2163 | wake_up(&module_wq); | ||
2135 | return ret; | 2164 | return ret; |
2136 | } | 2165 | } |
2137 | 2166 | ||
@@ -2146,6 +2175,7 @@ sys_init_module(void __user *umod, | |||
2146 | mod->init_size = 0; | 2175 | mod->init_size = 0; |
2147 | mod->init_text_size = 0; | 2176 | mod->init_text_size = 0; |
2148 | mutex_unlock(&module_mutex); | 2177 | mutex_unlock(&module_mutex); |
2178 | wake_up(&module_wq); | ||
2149 | 2179 | ||
2150 | return 0; | 2180 | return 0; |
2151 | } | 2181 | } |
@@ -2210,14 +2240,13 @@ static const char *get_ksymbol(struct module *mod, | |||
2210 | return mod->strtab + mod->symtab[best].st_name; | 2240 | return mod->strtab + mod->symtab[best].st_name; |
2211 | } | 2241 | } |
2212 | 2242 | ||
2213 | /* For kallsyms to ask for address resolution. NULL means not found. | 2243 | /* For kallsyms to ask for address resolution. NULL means not found. Careful |
2214 | We don't lock, as this is used for oops resolution and races are a | 2244 | * not to lock to avoid deadlock on oopses, simply disable preemption. */ |
2215 | lesser concern. */ | 2245 | char *module_address_lookup(unsigned long addr, |
2216 | /* FIXME: Risky: returns a pointer into a module w/o lock */ | 2246 | unsigned long *size, |
2217 | const char *module_address_lookup(unsigned long addr, | 2247 | unsigned long *offset, |
2218 | unsigned long *size, | 2248 | char **modname, |
2219 | unsigned long *offset, | 2249 | char *namebuf) |
2220 | char **modname) | ||
2221 | { | 2250 | { |
2222 | struct module *mod; | 2251 | struct module *mod; |
2223 | const char *ret = NULL; | 2252 | const char *ret = NULL; |
@@ -2232,8 +2261,13 @@ const char *module_address_lookup(unsigned long addr, | |||
2232 | break; | 2261 | break; |
2233 | } | 2262 | } |
2234 | } | 2263 | } |
2264 | /* Make a copy in here where it's safe */ | ||
2265 | if (ret) { | ||
2266 | strncpy(namebuf, ret, KSYM_NAME_LEN - 1); | ||
2267 | ret = namebuf; | ||
2268 | } | ||
2235 | preempt_enable(); | 2269 | preempt_enable(); |
2236 | return ret; | 2270 | return (char *)ret; |
2237 | } | 2271 | } |
2238 | 2272 | ||
2239 | int lookup_module_symbol_name(unsigned long addr, char *symname) | 2273 | int lookup_module_symbol_name(unsigned long addr, char *symname) |
diff --git a/kernel/params.c b/kernel/params.c index 67f65ee7211d..42fe5e6126c0 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -376,8 +376,6 @@ int param_get_string(char *buffer, struct kernel_param *kp) | |||
376 | 376 | ||
377 | extern struct kernel_param __start___param[], __stop___param[]; | 377 | extern struct kernel_param __start___param[], __stop___param[]; |
378 | 378 | ||
379 | #define MAX_KBUILD_MODNAME KOBJ_NAME_LEN | ||
380 | |||
381 | struct param_attribute | 379 | struct param_attribute |
382 | { | 380 | { |
383 | struct module_attribute mattr; | 381 | struct module_attribute mattr; |
@@ -587,7 +585,7 @@ static void __init param_sysfs_builtin(void) | |||
587 | { | 585 | { |
588 | struct kernel_param *kp, *kp_begin = NULL; | 586 | struct kernel_param *kp, *kp_begin = NULL; |
589 | unsigned int i, name_len, count = 0; | 587 | unsigned int i, name_len, count = 0; |
590 | char modname[MAX_KBUILD_MODNAME + 1] = ""; | 588 | char modname[MODULE_NAME_LEN + 1] = ""; |
591 | 589 | ||
592 | for (i=0; i < __stop___param - __start___param; i++) { | 590 | for (i=0; i < __stop___param - __start___param; i++) { |
593 | char *dot; | 591 | char *dot; |
@@ -595,12 +593,12 @@ static void __init param_sysfs_builtin(void) | |||
595 | 593 | ||
596 | kp = &__start___param[i]; | 594 | kp = &__start___param[i]; |
597 | max_name_len = | 595 | max_name_len = |
598 | min_t(size_t, MAX_KBUILD_MODNAME, strlen(kp->name)); | 596 | min_t(size_t, MODULE_NAME_LEN, strlen(kp->name)); |
599 | 597 | ||
600 | dot = memchr(kp->name, '.', max_name_len); | 598 | dot = memchr(kp->name, '.', max_name_len); |
601 | if (!dot) { | 599 | if (!dot) { |
602 | DEBUGP("couldn't find period in first %d characters " | 600 | DEBUGP("couldn't find period in first %d characters " |
603 | "of %s\n", MAX_KBUILD_MODNAME, kp->name); | 601 | "of %s\n", MODULE_NAME_LEN, kp->name); |
604 | continue; | 602 | continue; |
605 | } | 603 | } |
606 | name_len = dot - kp->name; | 604 | name_len = dot - kp->name; |