diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 92 | 
1 files changed, 54 insertions, 38 deletions
| diff --git a/kernel/module.c b/kernel/module.c index dd2a54155b54..496dcb57b608 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -43,7 +43,6 @@ | |||
| 43 | #include <linux/device.h> | 43 | #include <linux/device.h> | 
| 44 | #include <linux/string.h> | 44 | #include <linux/string.h> | 
| 45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> | 
| 46 | #include <linux/unwind.h> | ||
| 47 | #include <linux/rculist.h> | 46 | #include <linux/rculist.h> | 
| 48 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> | 
| 49 | #include <asm/cacheflush.h> | 48 | #include <asm/cacheflush.h> | 
| @@ -757,8 +756,16 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
| 757 | return -EFAULT; | 756 | return -EFAULT; | 
| 758 | name[MODULE_NAME_LEN-1] = '\0'; | 757 | name[MODULE_NAME_LEN-1] = '\0'; | 
| 759 | 758 | ||
| 760 | if (mutex_lock_interruptible(&module_mutex) != 0) | 759 | /* Create stop_machine threads since free_module relies on | 
| 761 | return -EINTR; | 760 | * a non-failing stop_machine call. */ | 
| 761 | ret = stop_machine_create(); | ||
| 762 | if (ret) | ||
| 763 | return ret; | ||
| 764 | |||
| 765 | if (mutex_lock_interruptible(&module_mutex) != 0) { | ||
| 766 | ret = -EINTR; | ||
| 767 | goto out_stop; | ||
| 768 | } | ||
| 762 | 769 | ||
| 763 | mod = find_module(name); | 770 | mod = find_module(name); | 
| 764 | if (!mod) { | 771 | if (!mod) { | 
| @@ -817,10 +824,12 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
| 817 | 824 | ||
| 818 | out: | 825 | out: | 
| 819 | mutex_unlock(&module_mutex); | 826 | mutex_unlock(&module_mutex); | 
| 827 | out_stop: | ||
| 828 | stop_machine_destroy(); | ||
| 820 | return ret; | 829 | return ret; | 
| 821 | } | 830 | } | 
| 822 | 831 | ||
| 823 | static void print_unload_info(struct seq_file *m, struct module *mod) | 832 | static inline void print_unload_info(struct seq_file *m, struct module *mod) | 
| 824 | { | 833 | { | 
| 825 | struct module_use *use; | 834 | struct module_use *use; | 
| 826 | int printed_something = 0; | 835 | int printed_something = 0; | 
| @@ -893,7 +902,7 @@ void module_put(struct module *module) | |||
| 893 | EXPORT_SYMBOL(module_put); | 902 | EXPORT_SYMBOL(module_put); | 
| 894 | 903 | ||
| 895 | #else /* !CONFIG_MODULE_UNLOAD */ | 904 | #else /* !CONFIG_MODULE_UNLOAD */ | 
| 896 | static void print_unload_info(struct seq_file *m, struct module *mod) | 905 | static inline void print_unload_info(struct seq_file *m, struct module *mod) | 
| 897 | { | 906 | { | 
| 898 | /* We don't know the usage count, or what modules are using. */ | 907 | /* We don't know the usage count, or what modules are using. */ | 
| 899 | seq_printf(m, " - -"); | 908 | seq_printf(m, " - -"); | 
| @@ -1439,8 +1448,6 @@ static void free_module(struct module *mod) | |||
| 1439 | remove_sect_attrs(mod); | 1448 | remove_sect_attrs(mod); | 
| 1440 | mod_kobject_remove(mod); | 1449 | mod_kobject_remove(mod); | 
| 1441 | 1450 | ||
| 1442 | unwind_remove_table(mod->unwind_info, 0); | ||
| 1443 | |||
| 1444 | /* Arch-specific cleanup. */ | 1451 | /* Arch-specific cleanup. */ | 
| 1445 | module_arch_cleanup(mod); | 1452 | module_arch_cleanup(mod); | 
| 1446 | 1453 | ||
| @@ -1578,11 +1585,21 @@ static int simplify_symbols(Elf_Shdr *sechdrs, | |||
| 1578 | return ret; | 1585 | return ret; | 
| 1579 | } | 1586 | } | 
| 1580 | 1587 | ||
| 1588 | /* Additional bytes needed by arch in front of individual sections */ | ||
| 1589 | unsigned int __weak arch_mod_section_prepend(struct module *mod, | ||
| 1590 | unsigned int section) | ||
| 1591 | { | ||
| 1592 | /* default implementation just returns zero */ | ||
| 1593 | return 0; | ||
| 1594 | } | ||
| 1595 | |||
| 1581 | /* Update size with this section: return offset. */ | 1596 | /* Update size with this section: return offset. */ | 
| 1582 | static long get_offset(unsigned int *size, Elf_Shdr *sechdr) | 1597 | static long get_offset(struct module *mod, unsigned int *size, | 
| 1598 | Elf_Shdr *sechdr, unsigned int section) | ||
| 1583 | { | 1599 | { | 
| 1584 | long ret; | 1600 | long ret; | 
| 1585 | 1601 | ||
| 1602 | *size += arch_mod_section_prepend(mod, section); | ||
| 1586 | ret = ALIGN(*size, sechdr->sh_addralign ?: 1); | 1603 | ret = ALIGN(*size, sechdr->sh_addralign ?: 1); | 
| 1587 | *size = ret + sechdr->sh_size; | 1604 | *size = ret + sechdr->sh_size; | 
| 1588 | return ret; | 1605 | return ret; | 
| @@ -1622,7 +1639,7 @@ static void layout_sections(struct module *mod, | |||
| 1622 | || strncmp(secstrings + s->sh_name, | 1639 | || strncmp(secstrings + s->sh_name, | 
| 1623 | ".init", 5) == 0) | 1640 | ".init", 5) == 0) | 
| 1624 | continue; | 1641 | continue; | 
| 1625 | s->sh_entsize = get_offset(&mod->core_size, s); | 1642 | s->sh_entsize = get_offset(mod, &mod->core_size, s, i); | 
| 1626 | DEBUGP("\t%s\n", secstrings + s->sh_name); | 1643 | DEBUGP("\t%s\n", secstrings + s->sh_name); | 
| 1627 | } | 1644 | } | 
| 1628 | if (m == 0) | 1645 | if (m == 0) | 
| @@ -1640,7 +1657,7 @@ static void layout_sections(struct module *mod, | |||
| 1640 | || strncmp(secstrings + s->sh_name, | 1657 | || strncmp(secstrings + s->sh_name, | 
| 1641 | ".init", 5) != 0) | 1658 | ".init", 5) != 0) | 
| 1642 | continue; | 1659 | continue; | 
| 1643 | s->sh_entsize = (get_offset(&mod->init_size, s) | 1660 | s->sh_entsize = (get_offset(mod, &mod->init_size, s, i) | 
| 1644 | | INIT_OFFSET_MASK); | 1661 | | INIT_OFFSET_MASK); | 
| 1645 | DEBUGP("\t%s\n", secstrings + s->sh_name); | 1662 | DEBUGP("\t%s\n", secstrings + s->sh_name); | 
| 1646 | } | 1663 | } | 
| @@ -1725,15 +1742,15 @@ static const struct kernel_symbol *lookup_symbol(const char *name, | |||
| 1725 | return NULL; | 1742 | return NULL; | 
| 1726 | } | 1743 | } | 
| 1727 | 1744 | ||
| 1728 | static int is_exported(const char *name, const struct module *mod) | 1745 | static int is_exported(const char *name, unsigned long value, | 
| 1746 | const struct module *mod) | ||
| 1729 | { | 1747 | { | 
| 1730 | if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab)) | 1748 | const struct kernel_symbol *ks; | 
| 1731 | return 1; | 1749 | if (!mod) | 
| 1750 | ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab); | ||
| 1732 | else | 1751 | else | 
| 1733 | if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms)) | 1752 | ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms); | 
| 1734 | return 1; | 1753 | return ks != NULL && ks->value == value; | 
| 1735 | else | ||
| 1736 | return 0; | ||
| 1737 | } | 1754 | } | 
| 1738 | 1755 | ||
| 1739 | /* As per nm */ | 1756 | /* As per nm */ | 
| @@ -1847,7 +1864,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1847 | unsigned int symindex = 0; | 1864 | unsigned int symindex = 0; | 
| 1848 | unsigned int strindex = 0; | 1865 | unsigned int strindex = 0; | 
| 1849 | unsigned int modindex, versindex, infoindex, pcpuindex; | 1866 | unsigned int modindex, versindex, infoindex, pcpuindex; | 
| 1850 | unsigned int unwindex = 0; | ||
| 1851 | unsigned int num_kp, num_mcount; | 1867 | unsigned int num_kp, num_mcount; | 
| 1852 | struct kernel_param *kp; | 1868 | struct kernel_param *kp; | 
| 1853 | struct module *mod; | 1869 | struct module *mod; | 
| @@ -1865,6 +1881,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1865 | /* vmalloc barfs on "unusual" numbers. Check here */ | 1881 | /* vmalloc barfs on "unusual" numbers. Check here */ | 
| 1866 | if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) | 1882 | if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) | 
| 1867 | return ERR_PTR(-ENOMEM); | 1883 | return ERR_PTR(-ENOMEM); | 
| 1884 | |||
| 1885 | /* Create stop_machine threads since the error path relies on | ||
| 1886 | * a non-failing stop_machine call. */ | ||
| 1887 | err = stop_machine_create(); | ||
| 1888 | if (err) | ||
| 1889 | goto free_hdr; | ||
| 1890 | |||
| 1868 | if (copy_from_user(hdr, umod, len) != 0) { | 1891 | if (copy_from_user(hdr, umod, len) != 0) { | 
| 1869 | err = -EFAULT; | 1892 | err = -EFAULT; | 
| 1870 | goto free_hdr; | 1893 | goto free_hdr; | 
| @@ -1930,9 +1953,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1930 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); | 1953 | versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); | 
| 1931 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); | 1954 | infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); | 
| 1932 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); | 1955 | pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); | 
| 1933 | #ifdef ARCH_UNWIND_SECTION_NAME | ||
| 1934 | unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME); | ||
| 1935 | #endif | ||
| 1936 | 1956 | ||
| 1937 | /* Don't keep modinfo and version sections. */ | 1957 | /* Don't keep modinfo and version sections. */ | 
| 1938 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 1958 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 
| @@ -1942,8 +1962,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1942 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | 1962 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | 
| 1943 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 1963 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 
| 1944 | #endif | 1964 | #endif | 
| 1945 | if (unwindex) | ||
| 1946 | sechdrs[unwindex].sh_flags |= SHF_ALLOC; | ||
| 1947 | 1965 | ||
| 1948 | /* Check module struct version now, before we try to use module. */ | 1966 | /* Check module struct version now, before we try to use module. */ | 
| 1949 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 1967 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 
| @@ -2240,14 +2258,10 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2240 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2258 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 
| 2241 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2259 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 
| 2242 | 2260 | ||
| 2243 | /* Size of section 0 is 0, so this works well if no unwind info. */ | ||
| 2244 | mod->unwind_info = unwind_add_table(mod, | ||
| 2245 | (void *)sechdrs[unwindex].sh_addr, | ||
| 2246 | sechdrs[unwindex].sh_size); | ||
| 2247 | |||
| 2248 | /* Get rid of temporary copy */ | 2261 | /* Get rid of temporary copy */ | 
| 2249 | vfree(hdr); | 2262 | vfree(hdr); | 
| 2250 | 2263 | ||
| 2264 | stop_machine_destroy(); | ||
| 2251 | /* Done! */ | 2265 | /* Done! */ | 
| 2252 | return mod; | 2266 | return mod; | 
| 2253 | 2267 | ||
| @@ -2270,6 +2284,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2270 | kfree(args); | 2284 | kfree(args); | 
| 2271 | free_hdr: | 2285 | free_hdr: | 
| 2272 | vfree(hdr); | 2286 | vfree(hdr); | 
| 2287 | stop_machine_destroy(); | ||
| 2273 | return ERR_PTR(err); | 2288 | return ERR_PTR(err); | 
| 2274 | 2289 | ||
| 2275 | truncated: | 2290 | truncated: | 
| @@ -2337,11 +2352,12 @@ sys_init_module(void __user *umod, | |||
| 2337 | /* Now it's a first class citizen! Wake up anyone waiting for it. */ | 2352 | /* Now it's a first class citizen! Wake up anyone waiting for it. */ | 
| 2338 | mod->state = MODULE_STATE_LIVE; | 2353 | mod->state = MODULE_STATE_LIVE; | 
| 2339 | wake_up(&module_wq); | 2354 | wake_up(&module_wq); | 
| 2355 | blocking_notifier_call_chain(&module_notify_list, | ||
| 2356 | MODULE_STATE_LIVE, mod); | ||
| 2340 | 2357 | ||
| 2341 | mutex_lock(&module_mutex); | 2358 | mutex_lock(&module_mutex); | 
| 2342 | /* Drop initial reference. */ | 2359 | /* Drop initial reference. */ | 
| 2343 | module_put(mod); | 2360 | module_put(mod); | 
| 2344 | unwind_remove_table(mod->unwind_info, 1); | ||
| 2345 | module_free(mod, mod->module_init); | 2361 | module_free(mod, mod->module_init); | 
| 2346 | mod->module_init = NULL; | 2362 | mod->module_init = NULL; | 
| 2347 | mod->init_size = 0; | 2363 | mod->init_size = 0; | 
| @@ -2376,7 +2392,7 @@ static const char *get_ksymbol(struct module *mod, | |||
| 2376 | unsigned long nextval; | 2392 | unsigned long nextval; | 
| 2377 | 2393 | ||
| 2378 | /* At worse, next value is at end of module */ | 2394 | /* At worse, next value is at end of module */ | 
| 2379 | if (within(addr, mod->module_init, mod->init_size)) | 2395 | if (within_module_init(addr, mod)) | 
| 2380 | nextval = (unsigned long)mod->module_init+mod->init_text_size; | 2396 | nextval = (unsigned long)mod->module_init+mod->init_text_size; | 
| 2381 | else | 2397 | else | 
| 2382 | nextval = (unsigned long)mod->module_core+mod->core_text_size; | 2398 | nextval = (unsigned long)mod->module_core+mod->core_text_size; | 
| @@ -2424,8 +2440,8 @@ const char *module_address_lookup(unsigned long addr, | |||
| 2424 | 2440 | ||
| 2425 | preempt_disable(); | 2441 | preempt_disable(); | 
| 2426 | list_for_each_entry_rcu(mod, &modules, list) { | 2442 | list_for_each_entry_rcu(mod, &modules, list) { | 
| 2427 | if (within(addr, mod->module_init, mod->init_size) | 2443 | if (within_module_init(addr, mod) || | 
| 2428 | || within(addr, mod->module_core, mod->core_size)) { | 2444 | within_module_core(addr, mod)) { | 
| 2429 | if (modname) | 2445 | if (modname) | 
| 2430 | *modname = mod->name; | 2446 | *modname = mod->name; | 
| 2431 | ret = get_ksymbol(mod, addr, size, offset); | 2447 | ret = get_ksymbol(mod, addr, size, offset); | 
| @@ -2447,8 +2463,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
| 2447 | 2463 | ||
| 2448 | preempt_disable(); | 2464 | preempt_disable(); | 
| 2449 | list_for_each_entry_rcu(mod, &modules, list) { | 2465 | list_for_each_entry_rcu(mod, &modules, list) { | 
| 2450 | if (within(addr, mod->module_init, mod->init_size) || | 2466 | if (within_module_init(addr, mod) || | 
| 2451 | within(addr, mod->module_core, mod->core_size)) { | 2467 | within_module_core(addr, mod)) { | 
| 2452 | const char *sym; | 2468 | const char *sym; | 
| 2453 | 2469 | ||
| 2454 | sym = get_ksymbol(mod, addr, NULL, NULL); | 2470 | sym = get_ksymbol(mod, addr, NULL, NULL); | 
| @@ -2471,8 +2487,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
| 2471 | 2487 | ||
| 2472 | preempt_disable(); | 2488 | preempt_disable(); | 
| 2473 | list_for_each_entry_rcu(mod, &modules, list) { | 2489 | list_for_each_entry_rcu(mod, &modules, list) { | 
| 2474 | if (within(addr, mod->module_init, mod->init_size) || | 2490 | if (within_module_init(addr, mod) || | 
| 2475 | within(addr, mod->module_core, mod->core_size)) { | 2491 | within_module_core(addr, mod)) { | 
| 2476 | const char *sym; | 2492 | const char *sym; | 
| 2477 | 2493 | ||
| 2478 | sym = get_ksymbol(mod, addr, size, offset); | 2494 | sym = get_ksymbol(mod, addr, size, offset); | 
| @@ -2504,7 +2520,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
| 2504 | strlcpy(name, mod->strtab + mod->symtab[symnum].st_name, | 2520 | strlcpy(name, mod->strtab + mod->symtab[symnum].st_name, | 
| 2505 | KSYM_NAME_LEN); | 2521 | KSYM_NAME_LEN); | 
| 2506 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); | 2522 | strlcpy(module_name, mod->name, MODULE_NAME_LEN); | 
| 2507 | *exported = is_exported(name, mod); | 2523 | *exported = is_exported(name, *value, mod); | 
| 2508 | preempt_enable(); | 2524 | preempt_enable(); | 
| 2509 | return 0; | 2525 | return 0; | 
| 2510 | } | 2526 | } | 
| @@ -2691,7 +2707,7 @@ int is_module_address(unsigned long addr) | |||
| 2691 | preempt_disable(); | 2707 | preempt_disable(); | 
| 2692 | 2708 | ||
| 2693 | list_for_each_entry_rcu(mod, &modules, list) { | 2709 | list_for_each_entry_rcu(mod, &modules, list) { | 
| 2694 | if (within(addr, mod->module_core, mod->core_size)) { | 2710 | if (within_module_core(addr, mod)) { | 
| 2695 | preempt_enable(); | 2711 | preempt_enable(); | 
| 2696 | return 1; | 2712 | return 1; | 
| 2697 | } | 2713 | } | 
