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