diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 137 |
1 files changed, 129 insertions, 8 deletions
diff --git a/kernel/module.c b/kernel/module.c index 9db11911e04b..0d8d21ee792c 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -46,6 +46,8 @@ | |||
| 46 | #include <asm/cacheflush.h> | 46 | #include <asm/cacheflush.h> |
| 47 | #include <linux/license.h> | 47 | #include <linux/license.h> |
| 48 | #include <asm/sections.h> | 48 | #include <asm/sections.h> |
| 49 | #include <linux/tracepoint.h> | ||
| 50 | #include <linux/ftrace.h> | ||
| 49 | 51 | ||
| 50 | #if 0 | 52 | #if 0 |
| 51 | #define DEBUGP printk | 53 | #define DEBUGP printk |
| @@ -100,7 +102,7 @@ static inline int strong_try_module_get(struct module *mod) | |||
| 100 | static inline void add_taint_module(struct module *mod, unsigned flag) | 102 | static inline void add_taint_module(struct module *mod, unsigned flag) |
| 101 | { | 103 | { |
| 102 | add_taint(flag); | 104 | add_taint(flag); |
| 103 | mod->taints |= flag; | 105 | mod->taints |= (1U << flag); |
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | /* | 108 | /* |
| @@ -784,6 +786,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
| 784 | mutex_lock(&module_mutex); | 786 | mutex_lock(&module_mutex); |
| 785 | /* Store the name of the last unloaded module for diagnostic purposes */ | 787 | /* Store the name of the last unloaded module for diagnostic purposes */ |
| 786 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); | 788 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
| 789 | unregister_dynamic_debug_module(mod->name); | ||
| 787 | free_module(mod); | 790 | free_module(mod); |
| 788 | 791 | ||
| 789 | out: | 792 | out: |
| @@ -923,7 +926,7 @@ static const char vermagic[] = VERMAGIC_STRING; | |||
| 923 | static int try_to_force_load(struct module *mod, const char *symname) | 926 | static int try_to_force_load(struct module *mod, const char *symname) |
| 924 | { | 927 | { |
| 925 | #ifdef CONFIG_MODULE_FORCE_LOAD | 928 | #ifdef CONFIG_MODULE_FORCE_LOAD |
| 926 | if (!(tainted & TAINT_FORCED_MODULE)) | 929 | if (!test_taint(TAINT_FORCED_MODULE)) |
| 927 | printk("%s: no version for \"%s\" found: kernel tainted.\n", | 930 | printk("%s: no version for \"%s\" found: kernel tainted.\n", |
| 928 | mod->name, symname); | 931 | mod->name, symname); |
| 929 | add_taint_module(mod, TAINT_FORCED_MODULE); | 932 | add_taint_module(mod, TAINT_FORCED_MODULE); |
| @@ -1033,7 +1036,7 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, | |||
| 1033 | const unsigned long *crc; | 1036 | const unsigned long *crc; |
| 1034 | 1037 | ||
| 1035 | ret = find_symbol(name, &owner, &crc, | 1038 | ret = find_symbol(name, &owner, &crc, |
| 1036 | !(mod->taints & TAINT_PROPRIETARY_MODULE), true); | 1039 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
| 1037 | if (!IS_ERR_VALUE(ret)) { | 1040 | if (!IS_ERR_VALUE(ret)) { |
| 1038 | /* use_module can fail due to OOM, | 1041 | /* use_module can fail due to OOM, |
| 1039 | or module initialization or unloading */ | 1042 | or module initialization or unloading */ |
| @@ -1173,7 +1176,7 @@ static void free_notes_attrs(struct module_notes_attrs *notes_attrs, | |||
| 1173 | while (i-- > 0) | 1176 | while (i-- > 0) |
| 1174 | sysfs_remove_bin_file(notes_attrs->dir, | 1177 | sysfs_remove_bin_file(notes_attrs->dir, |
| 1175 | ¬es_attrs->attrs[i]); | 1178 | ¬es_attrs->attrs[i]); |
| 1176 | kobject_del(notes_attrs->dir); | 1179 | kobject_put(notes_attrs->dir); |
| 1177 | } | 1180 | } |
| 1178 | kfree(notes_attrs); | 1181 | kfree(notes_attrs); |
| 1179 | } | 1182 | } |
| @@ -1429,6 +1432,9 @@ static void free_module(struct module *mod) | |||
| 1429 | /* Module unload stuff */ | 1432 | /* Module unload stuff */ |
| 1430 | module_unload_free(mod); | 1433 | module_unload_free(mod); |
| 1431 | 1434 | ||
| 1435 | /* release any pointers to mcount in this module */ | ||
| 1436 | ftrace_release(mod->module_core, mod->core_size); | ||
| 1437 | |||
| 1432 | /* This may be NULL, but that's OK */ | 1438 | /* This may be NULL, but that's OK */ |
| 1433 | module_free(mod, mod->module_init); | 1439 | module_free(mod, mod->module_init); |
| 1434 | kfree(mod->args); | 1440 | kfree(mod->args); |
| @@ -1634,7 +1640,7 @@ static void set_license(struct module *mod, const char *license) | |||
| 1634 | license = "unspecified"; | 1640 | license = "unspecified"; |
| 1635 | 1641 | ||
| 1636 | if (!license_is_gpl_compatible(license)) { | 1642 | if (!license_is_gpl_compatible(license)) { |
| 1637 | if (!(tainted & TAINT_PROPRIETARY_MODULE)) | 1643 | if (!test_taint(TAINT_PROPRIETARY_MODULE)) |
| 1638 | printk(KERN_WARNING "%s: module license '%s' taints " | 1644 | printk(KERN_WARNING "%s: module license '%s' taints " |
| 1639 | "kernel.\n", mod->name, license); | 1645 | "kernel.\n", mod->name, license); |
| 1640 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | 1646 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
| @@ -1783,6 +1789,33 @@ static inline void add_kallsyms(struct module *mod, | |||
| 1783 | } | 1789 | } |
| 1784 | #endif /* CONFIG_KALLSYMS */ | 1790 | #endif /* CONFIG_KALLSYMS */ |
| 1785 | 1791 | ||
| 1792 | #ifdef CONFIG_DYNAMIC_PRINTK_DEBUG | ||
| 1793 | static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex) | ||
| 1794 | { | ||
| 1795 | struct mod_debug *debug_info; | ||
| 1796 | unsigned long pos, end; | ||
| 1797 | unsigned int num_verbose; | ||
| 1798 | |||
| 1799 | pos = sechdrs[verboseindex].sh_addr; | ||
| 1800 | num_verbose = sechdrs[verboseindex].sh_size / | ||
| 1801 | sizeof(struct mod_debug); | ||
| 1802 | end = pos + (num_verbose * sizeof(struct mod_debug)); | ||
| 1803 | |||
| 1804 | for (; pos < end; pos += sizeof(struct mod_debug)) { | ||
| 1805 | debug_info = (struct mod_debug *)pos; | ||
| 1806 | register_dynamic_debug_module(debug_info->modname, | ||
| 1807 | debug_info->type, debug_info->logical_modname, | ||
| 1808 | debug_info->flag_names, debug_info->hash, | ||
| 1809 | debug_info->hash2); | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | #else | ||
| 1813 | static inline void dynamic_printk_setup(Elf_Shdr *sechdrs, | ||
| 1814 | unsigned int verboseindex) | ||
| 1815 | { | ||
| 1816 | } | ||
| 1817 | #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ | ||
| 1818 | |||
| 1786 | static void *module_alloc_update_bounds(unsigned long size) | 1819 | static void *module_alloc_update_bounds(unsigned long size) |
| 1787 | { | 1820 | { |
| 1788 | void *ret = module_alloc(size); | 1821 | void *ret = module_alloc(size); |
| @@ -1806,6 +1839,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1806 | Elf_Ehdr *hdr; | 1839 | Elf_Ehdr *hdr; |
| 1807 | Elf_Shdr *sechdrs; | 1840 | Elf_Shdr *sechdrs; |
| 1808 | char *secstrings, *args, *modmagic, *strtab = NULL; | 1841 | char *secstrings, *args, *modmagic, *strtab = NULL; |
| 1842 | char *staging; | ||
| 1809 | unsigned int i; | 1843 | unsigned int i; |
| 1810 | unsigned int symindex = 0; | 1844 | unsigned int symindex = 0; |
| 1811 | unsigned int strindex = 0; | 1845 | unsigned int strindex = 0; |
| @@ -1831,9 +1865,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1831 | #endif | 1865 | #endif |
| 1832 | unsigned int markersindex; | 1866 | unsigned int markersindex; |
| 1833 | unsigned int markersstringsindex; | 1867 | unsigned int markersstringsindex; |
| 1868 | unsigned int verboseindex; | ||
| 1869 | unsigned int tracepointsindex; | ||
| 1870 | unsigned int tracepointsstringsindex; | ||
| 1871 | unsigned int mcountindex; | ||
| 1834 | struct module *mod; | 1872 | struct module *mod; |
| 1835 | long err = 0; | 1873 | long err = 0; |
| 1836 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 1874 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
| 1875 | void *mseg; | ||
| 1837 | struct exception_table_entry *extable; | 1876 | struct exception_table_entry *extable; |
| 1838 | mm_segment_t old_fs; | 1877 | mm_segment_t old_fs; |
| 1839 | 1878 | ||
| @@ -1960,6 +1999,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1960 | goto free_hdr; | 1999 | goto free_hdr; |
| 1961 | } | 2000 | } |
| 1962 | 2001 | ||
| 2002 | staging = get_modinfo(sechdrs, infoindex, "staging"); | ||
| 2003 | if (staging) { | ||
| 2004 | add_taint_module(mod, TAINT_CRAP); | ||
| 2005 | printk(KERN_WARNING "%s: module is from the staging directory," | ||
| 2006 | " the quality is unknown, you have been warned.\n", | ||
| 2007 | mod->name); | ||
| 2008 | } | ||
| 2009 | |||
| 1963 | /* Now copy in args */ | 2010 | /* Now copy in args */ |
| 1964 | args = strndup_user(uargs, ~0UL >> 1); | 2011 | args = strndup_user(uargs, ~0UL >> 1); |
| 1965 | if (IS_ERR(args)) { | 2012 | if (IS_ERR(args)) { |
| @@ -2117,6 +2164,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2117 | markersindex = find_sec(hdr, sechdrs, secstrings, "__markers"); | 2164 | markersindex = find_sec(hdr, sechdrs, secstrings, "__markers"); |
| 2118 | markersstringsindex = find_sec(hdr, sechdrs, secstrings, | 2165 | markersstringsindex = find_sec(hdr, sechdrs, secstrings, |
| 2119 | "__markers_strings"); | 2166 | "__markers_strings"); |
| 2167 | verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose"); | ||
| 2168 | tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints"); | ||
| 2169 | tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings, | ||
| 2170 | "__tracepoints_strings"); | ||
| 2171 | |||
| 2172 | mcountindex = find_sec(hdr, sechdrs, secstrings, | ||
| 2173 | "__mcount_loc"); | ||
| 2120 | 2174 | ||
| 2121 | /* Now do relocations. */ | 2175 | /* Now do relocations. */ |
| 2122 | for (i = 1; i < hdr->e_shnum; i++) { | 2176 | for (i = 1; i < hdr->e_shnum; i++) { |
| @@ -2144,6 +2198,12 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2144 | mod->num_markers = | 2198 | mod->num_markers = |
| 2145 | sechdrs[markersindex].sh_size / sizeof(*mod->markers); | 2199 | sechdrs[markersindex].sh_size / sizeof(*mod->markers); |
| 2146 | #endif | 2200 | #endif |
| 2201 | #ifdef CONFIG_TRACEPOINTS | ||
| 2202 | mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr; | ||
| 2203 | mod->num_tracepoints = | ||
| 2204 | sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints); | ||
| 2205 | #endif | ||
| 2206 | |||
| 2147 | 2207 | ||
| 2148 | /* Find duplicate symbols */ | 2208 | /* Find duplicate symbols */ |
| 2149 | err = verify_export_symbols(mod); | 2209 | err = verify_export_symbols(mod); |
| @@ -2162,11 +2222,22 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2162 | 2222 | ||
| 2163 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); | 2223 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); |
| 2164 | 2224 | ||
| 2225 | if (!mod->taints) { | ||
| 2165 | #ifdef CONFIG_MARKERS | 2226 | #ifdef CONFIG_MARKERS |
| 2166 | if (!mod->taints) | ||
| 2167 | marker_update_probe_range(mod->markers, | 2227 | marker_update_probe_range(mod->markers, |
| 2168 | mod->markers + mod->num_markers); | 2228 | mod->markers + mod->num_markers); |
| 2169 | #endif | 2229 | #endif |
| 2230 | dynamic_printk_setup(sechdrs, verboseindex); | ||
| 2231 | #ifdef CONFIG_TRACEPOINTS | ||
| 2232 | tracepoint_update_probe_range(mod->tracepoints, | ||
| 2233 | mod->tracepoints + mod->num_tracepoints); | ||
| 2234 | #endif | ||
| 2235 | } | ||
| 2236 | |||
| 2237 | /* sechdrs[0].sh_size is always zero */ | ||
| 2238 | mseg = (void *)sechdrs[mcountindex].sh_addr; | ||
| 2239 | ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size); | ||
| 2240 | |||
| 2170 | err = module_finalize(hdr, sechdrs, mod); | 2241 | err = module_finalize(hdr, sechdrs, mod); |
| 2171 | if (err < 0) | 2242 | if (err < 0) |
| 2172 | goto cleanup; | 2243 | goto cleanup; |
| @@ -2236,6 +2307,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2236 | cleanup: | 2307 | cleanup: |
| 2237 | kobject_del(&mod->mkobj.kobj); | 2308 | kobject_del(&mod->mkobj.kobj); |
| 2238 | kobject_put(&mod->mkobj.kobj); | 2309 | kobject_put(&mod->mkobj.kobj); |
| 2310 | ftrace_release(mod->module_core, mod->core_size); | ||
| 2239 | free_unload: | 2311 | free_unload: |
| 2240 | module_unload_free(mod); | 2312 | module_unload_free(mod); |
| 2241 | module_free(mod, mod->module_init); | 2313 | module_free(mod, mod->module_init); |
| @@ -2552,10 +2624,12 @@ static char *module_flags(struct module *mod, char *buf) | |||
| 2552 | mod->state == MODULE_STATE_GOING || | 2624 | mod->state == MODULE_STATE_GOING || |
| 2553 | mod->state == MODULE_STATE_COMING) { | 2625 | mod->state == MODULE_STATE_COMING) { |
| 2554 | buf[bx++] = '('; | 2626 | buf[bx++] = '('; |
| 2555 | if (mod->taints & TAINT_PROPRIETARY_MODULE) | 2627 | if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE)) |
| 2556 | buf[bx++] = 'P'; | 2628 | buf[bx++] = 'P'; |
| 2557 | if (mod->taints & TAINT_FORCED_MODULE) | 2629 | if (mod->taints & (1 << TAINT_FORCED_MODULE)) |
| 2558 | buf[bx++] = 'F'; | 2630 | buf[bx++] = 'F'; |
| 2631 | if (mod->taints & (1 << TAINT_CRAP)) | ||
| 2632 | buf[bx++] = 'C'; | ||
| 2559 | /* | 2633 | /* |
| 2560 | * TAINT_FORCED_RMMOD: could be added. | 2634 | * TAINT_FORCED_RMMOD: could be added. |
| 2561 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't | 2635 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't |
| @@ -2717,3 +2791,50 @@ void module_update_markers(void) | |||
| 2717 | mutex_unlock(&module_mutex); | 2791 | mutex_unlock(&module_mutex); |
| 2718 | } | 2792 | } |
| 2719 | #endif | 2793 | #endif |
| 2794 | |||
| 2795 | #ifdef CONFIG_TRACEPOINTS | ||
| 2796 | void module_update_tracepoints(void) | ||
| 2797 | { | ||
| 2798 | struct module *mod; | ||
| 2799 | |||
| 2800 | mutex_lock(&module_mutex); | ||
| 2801 | list_for_each_entry(mod, &modules, list) | ||
| 2802 | if (!mod->taints) | ||
| 2803 | tracepoint_update_probe_range(mod->tracepoints, | ||
| 2804 | mod->tracepoints + mod->num_tracepoints); | ||
| 2805 | mutex_unlock(&module_mutex); | ||
| 2806 | } | ||
| 2807 | |||
| 2808 | /* | ||
| 2809 | * Returns 0 if current not found. | ||
| 2810 | * Returns 1 if current found. | ||
| 2811 | */ | ||
| 2812 | int module_get_iter_tracepoints(struct tracepoint_iter *iter) | ||
| 2813 | { | ||
| 2814 | struct module *iter_mod; | ||
| 2815 | int found = 0; | ||
| 2816 | |||
| 2817 | mutex_lock(&module_mutex); | ||
| 2818 | list_for_each_entry(iter_mod, &modules, list) { | ||
| 2819 | if (!iter_mod->taints) { | ||
| 2820 | /* | ||
| 2821 | * Sorted module list | ||
| 2822 | */ | ||
| 2823 | if (iter_mod < iter->module) | ||
| 2824 | continue; | ||
| 2825 | else if (iter_mod > iter->module) | ||
| 2826 | iter->tracepoint = NULL; | ||
| 2827 | found = tracepoint_get_iter_range(&iter->tracepoint, | ||
| 2828 | iter_mod->tracepoints, | ||
| 2829 | iter_mod->tracepoints | ||
| 2830 | + iter_mod->num_tracepoints); | ||
| 2831 | if (found) { | ||
| 2832 | iter->module = iter_mod; | ||
| 2833 | break; | ||
| 2834 | } | ||
| 2835 | } | ||
| 2836 | } | ||
| 2837 | mutex_unlock(&module_mutex); | ||
| 2838 | return found; | ||
| 2839 | } | ||
| 2840 | #endif | ||
