diff options
| -rw-r--r-- | include/linux/module.h | 17 | ||||
| -rw-r--r-- | kernel/module.c | 159 | ||||
| -rw-r--r-- | kernel/params.c | 7 |
3 files changed, 165 insertions, 18 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 1c755b2f937d..482efc865acf 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -128,7 +128,10 @@ extern struct module __this_module; | |||
| 128 | */ | 128 | */ |
| 129 | #define MODULE_LICENSE(_license) MODULE_INFO(license, _license) | 129 | #define MODULE_LICENSE(_license) MODULE_INFO(license, _license) |
| 130 | 130 | ||
| 131 | /* Author, ideally of form NAME[, NAME]*[ and NAME] */ | 131 | /* |
| 132 | * Author(s), use "Name <email>" or just "Name", for multiple | ||
| 133 | * authors use multiple MODULE_AUTHOR() statements/lines. | ||
| 134 | */ | ||
| 132 | #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) | 135 | #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author) |
| 133 | 136 | ||
| 134 | /* What your module does. */ | 137 | /* What your module does. */ |
| @@ -308,10 +311,14 @@ struct module | |||
| 308 | #endif | 311 | #endif |
| 309 | 312 | ||
| 310 | #ifdef CONFIG_KALLSYMS | 313 | #ifdef CONFIG_KALLSYMS |
| 311 | /* We keep the symbol and string tables for kallsyms. */ | 314 | /* |
| 312 | Elf_Sym *symtab; | 315 | * We keep the symbol and string tables for kallsyms. |
| 313 | unsigned int num_symtab; | 316 | * The core_* fields below are temporary, loader-only (they |
| 314 | char *strtab; | 317 | * could really be discarded after module init). |
| 318 | */ | ||
| 319 | Elf_Sym *symtab, *core_symtab; | ||
| 320 | unsigned int num_symtab, core_num_syms; | ||
| 321 | char *strtab, *core_strtab; | ||
| 315 | 322 | ||
| 316 | /* Section attributes */ | 323 | /* Section attributes */ |
| 317 | struct module_sect_attrs *sect_attrs; | 324 | struct module_sect_attrs *sect_attrs; |
diff --git a/kernel/module.c b/kernel/module.c index e6bc4b28aa62..5a29397ca4b6 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -1797,6 +1797,17 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs, | |||
| 1797 | } | 1797 | } |
| 1798 | } | 1798 | } |
| 1799 | 1799 | ||
| 1800 | static void free_modinfo(struct module *mod) | ||
| 1801 | { | ||
| 1802 | struct module_attribute *attr; | ||
| 1803 | int i; | ||
| 1804 | |||
| 1805 | for (i = 0; (attr = modinfo_attrs[i]); i++) { | ||
| 1806 | if (attr->free) | ||
| 1807 | attr->free(mod); | ||
| 1808 | } | ||
| 1809 | } | ||
| 1810 | |||
| 1800 | #ifdef CONFIG_KALLSYMS | 1811 | #ifdef CONFIG_KALLSYMS |
| 1801 | 1812 | ||
| 1802 | /* lookup symbol in given range of kernel_symbols */ | 1813 | /* lookup symbol in given range of kernel_symbols */ |
| @@ -1862,13 +1873,93 @@ static char elf_type(const Elf_Sym *sym, | |||
| 1862 | return '?'; | 1873 | return '?'; |
| 1863 | } | 1874 | } |
| 1864 | 1875 | ||
| 1876 | static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, | ||
| 1877 | unsigned int shnum) | ||
| 1878 | { | ||
| 1879 | const Elf_Shdr *sec; | ||
| 1880 | |||
| 1881 | if (src->st_shndx == SHN_UNDEF | ||
| 1882 | || src->st_shndx >= shnum | ||
| 1883 | || !src->st_name) | ||
| 1884 | return false; | ||
| 1885 | |||
| 1886 | sec = sechdrs + src->st_shndx; | ||
| 1887 | if (!(sec->sh_flags & SHF_ALLOC) | ||
| 1888 | #ifndef CONFIG_KALLSYMS_ALL | ||
| 1889 | || !(sec->sh_flags & SHF_EXECINSTR) | ||
| 1890 | #endif | ||
| 1891 | || (sec->sh_entsize & INIT_OFFSET_MASK)) | ||
| 1892 | return false; | ||
| 1893 | |||
| 1894 | return true; | ||
| 1895 | } | ||
| 1896 | |||
| 1897 | static unsigned long layout_symtab(struct module *mod, | ||
| 1898 | Elf_Shdr *sechdrs, | ||
| 1899 | unsigned int symindex, | ||
| 1900 | unsigned int strindex, | ||
| 1901 | const Elf_Ehdr *hdr, | ||
| 1902 | const char *secstrings, | ||
| 1903 | unsigned long *pstroffs, | ||
| 1904 | unsigned long *strmap) | ||
| 1905 | { | ||
| 1906 | unsigned long symoffs; | ||
| 1907 | Elf_Shdr *symsect = sechdrs + symindex; | ||
| 1908 | Elf_Shdr *strsect = sechdrs + strindex; | ||
| 1909 | const Elf_Sym *src; | ||
| 1910 | const char *strtab; | ||
| 1911 | unsigned int i, nsrc, ndst; | ||
| 1912 | |||
| 1913 | /* Put symbol section at end of init part of module. */ | ||
| 1914 | symsect->sh_flags |= SHF_ALLOC; | ||
| 1915 | symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect, | ||
| 1916 | symindex) | INIT_OFFSET_MASK; | ||
| 1917 | DEBUGP("\t%s\n", secstrings + symsect->sh_name); | ||
| 1918 | |||
| 1919 | src = (void *)hdr + symsect->sh_offset; | ||
| 1920 | nsrc = symsect->sh_size / sizeof(*src); | ||
| 1921 | strtab = (void *)hdr + strsect->sh_offset; | ||
| 1922 | for (ndst = i = 1; i < nsrc; ++i, ++src) | ||
| 1923 | if (is_core_symbol(src, sechdrs, hdr->e_shnum)) { | ||
| 1924 | unsigned int j = src->st_name; | ||
| 1925 | |||
| 1926 | while(!__test_and_set_bit(j, strmap) && strtab[j]) | ||
| 1927 | ++j; | ||
| 1928 | ++ndst; | ||
| 1929 | } | ||
| 1930 | |||
| 1931 | /* Append room for core symbols at end of core part. */ | ||
| 1932 | symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); | ||
| 1933 | mod->core_size = symoffs + ndst * sizeof(Elf_Sym); | ||
| 1934 | |||
| 1935 | /* Put string table section at end of init part of module. */ | ||
| 1936 | strsect->sh_flags |= SHF_ALLOC; | ||
| 1937 | strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect, | ||
| 1938 | strindex) | INIT_OFFSET_MASK; | ||
| 1939 | DEBUGP("\t%s\n", secstrings + strsect->sh_name); | ||
| 1940 | |||
| 1941 | /* Append room for core symbols' strings at end of core part. */ | ||
| 1942 | *pstroffs = mod->core_size; | ||
| 1943 | __set_bit(0, strmap); | ||
| 1944 | mod->core_size += bitmap_weight(strmap, strsect->sh_size); | ||
| 1945 | |||
| 1946 | return symoffs; | ||
| 1947 | } | ||
| 1948 | |||
| 1865 | static void add_kallsyms(struct module *mod, | 1949 | static void add_kallsyms(struct module *mod, |
| 1866 | Elf_Shdr *sechdrs, | 1950 | Elf_Shdr *sechdrs, |
| 1951 | unsigned int shnum, | ||
| 1867 | unsigned int symindex, | 1952 | unsigned int symindex, |
| 1868 | unsigned int strindex, | 1953 | unsigned int strindex, |
| 1869 | const char *secstrings) | 1954 | unsigned long symoffs, |
| 1955 | unsigned long stroffs, | ||
| 1956 | const char *secstrings, | ||
| 1957 | unsigned long *strmap) | ||
| 1870 | { | 1958 | { |
| 1871 | unsigned int i; | 1959 | unsigned int i, ndst; |
| 1960 | const Elf_Sym *src; | ||
| 1961 | Elf_Sym *dst; | ||
| 1962 | char *s; | ||
| 1872 | 1963 | ||
| 1873 | mod->symtab = (void *)sechdrs[symindex].sh_addr; | 1964 | mod->symtab = (void *)sechdrs[symindex].sh_addr; |
| 1874 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); | 1965 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
| @@ -1878,13 +1969,44 @@ static void add_kallsyms(struct module *mod, | |||
| 1878 | for (i = 0; i < mod->num_symtab; i++) | 1969 | for (i = 0; i < mod->num_symtab; i++) |
| 1879 | mod->symtab[i].st_info | 1970 | mod->symtab[i].st_info |
| 1880 | = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); | 1971 | = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); |
| 1972 | |||
| 1973 | mod->core_symtab = dst = mod->module_core + symoffs; | ||
| 1974 | src = mod->symtab; | ||
| 1975 | *dst = *src; | ||
| 1976 | for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { | ||
| 1977 | if (!is_core_symbol(src, sechdrs, shnum)) | ||
| 1978 | continue; | ||
| 1979 | dst[ndst] = *src; | ||
| 1980 | dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); | ||
| 1981 | ++ndst; | ||
| 1982 | } | ||
| 1983 | mod->core_num_syms = ndst; | ||
| 1984 | |||
| 1985 | mod->core_strtab = s = mod->module_core + stroffs; | ||
| 1986 | for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i) | ||
| 1987 | if (test_bit(i, strmap)) | ||
| 1988 | *++s = mod->strtab[i]; | ||
| 1881 | } | 1989 | } |
| 1882 | #else | 1990 | #else |
| 1991 | static inline unsigned long layout_symtab(struct module *mod, | ||
| 1992 | Elf_Shdr *sechdrs, | ||
| 1993 | unsigned int symindex, | ||
| 1994 | unsigned int strindex, | ||
| 1995 | const Elf_Hdr *hdr, | ||
| 1996 | const char *secstrings, | ||
| 1997 | unsigned long *pstroffs, | ||
| 1998 | unsigned long *strmap) | ||
| 1999 | { | ||
| 2000 | } | ||
| 1883 | static inline void add_kallsyms(struct module *mod, | 2001 | static inline void add_kallsyms(struct module *mod, |
| 1884 | Elf_Shdr *sechdrs, | 2002 | Elf_Shdr *sechdrs, |
| 2003 | unsigned int shnum, | ||
| 1885 | unsigned int symindex, | 2004 | unsigned int symindex, |
| 1886 | unsigned int strindex, | 2005 | unsigned int strindex, |
| 1887 | const char *secstrings) | 2006 | unsigned long symoffs, |
| 2007 | unsigned long stroffs, | ||
| 2008 | const char *secstrings, | ||
| 2009 | const unsigned long *strmap) | ||
| 1888 | { | 2010 | { |
| 1889 | } | 2011 | } |
| 1890 | #endif /* CONFIG_KALLSYMS */ | 2012 | #endif /* CONFIG_KALLSYMS */ |
| @@ -1959,6 +2081,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1959 | struct module *mod; | 2081 | struct module *mod; |
| 1960 | long err = 0; | 2082 | long err = 0; |
| 1961 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 2083 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
| 2084 | #ifdef CONFIG_KALLSYMS | ||
| 2085 | unsigned long symoffs, stroffs, *strmap; | ||
| 2086 | #endif | ||
| 1962 | mm_segment_t old_fs; | 2087 | mm_segment_t old_fs; |
| 1963 | 2088 | ||
| 1964 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", | 2089 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
| @@ -2040,11 +2165,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2040 | /* Don't keep modinfo and version sections. */ | 2165 | /* Don't keep modinfo and version sections. */ |
| 2041 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2166 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2042 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2167 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2043 | #ifdef CONFIG_KALLSYMS | ||
| 2044 | /* Keep symbol and string tables for decoding later. */ | ||
| 2045 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | ||
| 2046 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | ||
| 2047 | #endif | ||
| 2048 | 2168 | ||
| 2049 | /* Check module struct version now, before we try to use module. */ | 2169 | /* Check module struct version now, before we try to use module. */ |
| 2050 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 2170 | if (!check_modstruct_version(sechdrs, versindex, mod)) { |
| @@ -2080,6 +2200,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2080 | goto free_hdr; | 2200 | goto free_hdr; |
| 2081 | } | 2201 | } |
| 2082 | 2202 | ||
| 2203 | strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size) | ||
| 2204 | * sizeof(long), GFP_KERNEL); | ||
| 2205 | if (!strmap) { | ||
| 2206 | err = -ENOMEM; | ||
| 2207 | goto free_mod; | ||
| 2208 | } | ||
| 2209 | |||
| 2083 | if (find_module(mod->name)) { | 2210 | if (find_module(mod->name)) { |
| 2084 | err = -EEXIST; | 2211 | err = -EEXIST; |
| 2085 | goto free_mod; | 2212 | goto free_mod; |
| @@ -2109,6 +2236,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2109 | this is done generically; there doesn't appear to be any | 2236 | this is done generically; there doesn't appear to be any |
| 2110 | special cases for the architectures. */ | 2237 | special cases for the architectures. */ |
| 2111 | layout_sections(mod, hdr, sechdrs, secstrings); | 2238 | layout_sections(mod, hdr, sechdrs, secstrings); |
| 2239 | symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr, | ||
| 2240 | secstrings, &stroffs, strmap); | ||
| 2112 | 2241 | ||
| 2113 | /* Do the allocs. */ | 2242 | /* Do the allocs. */ |
| 2114 | ptr = module_alloc_update_bounds(mod->core_size); | 2243 | ptr = module_alloc_update_bounds(mod->core_size); |
| @@ -2313,7 +2442,10 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2313 | percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, | 2442 | percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, |
| 2314 | sechdrs[pcpuindex].sh_size); | 2443 | sechdrs[pcpuindex].sh_size); |
| 2315 | 2444 | ||
| 2316 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); | 2445 | add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, |
| 2446 | symoffs, stroffs, secstrings, strmap); | ||
| 2447 | kfree(strmap); | ||
| 2448 | strmap = NULL; | ||
| 2317 | 2449 | ||
| 2318 | if (!mod->taints) { | 2450 | if (!mod->taints) { |
| 2319 | struct _ddebug *debug; | 2451 | struct _ddebug *debug; |
| @@ -2385,13 +2517,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2385 | synchronize_sched(); | 2517 | synchronize_sched(); |
| 2386 | module_arch_cleanup(mod); | 2518 | module_arch_cleanup(mod); |
| 2387 | cleanup: | 2519 | cleanup: |
| 2520 | free_modinfo(mod); | ||
| 2388 | kobject_del(&mod->mkobj.kobj); | 2521 | kobject_del(&mod->mkobj.kobj); |
| 2389 | kobject_put(&mod->mkobj.kobj); | 2522 | kobject_put(&mod->mkobj.kobj); |
| 2390 | free_unload: | 2523 | free_unload: |
| 2391 | module_unload_free(mod); | 2524 | module_unload_free(mod); |
| 2392 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2525 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) |
| 2393 | free_init: | ||
| 2394 | percpu_modfree(mod->refptr); | 2526 | percpu_modfree(mod->refptr); |
| 2527 | free_init: | ||
| 2395 | #endif | 2528 | #endif |
| 2396 | module_free(mod, mod->module_init); | 2529 | module_free(mod, mod->module_init); |
| 2397 | free_core: | 2530 | free_core: |
| @@ -2402,6 +2535,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2402 | percpu_modfree(percpu); | 2535 | percpu_modfree(percpu); |
| 2403 | free_mod: | 2536 | free_mod: |
| 2404 | kfree(args); | 2537 | kfree(args); |
| 2538 | kfree(strmap); | ||
| 2405 | free_hdr: | 2539 | free_hdr: |
| 2406 | vfree(hdr); | 2540 | vfree(hdr); |
| 2407 | return ERR_PTR(err); | 2541 | return ERR_PTR(err); |
| @@ -2491,6 +2625,11 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2491 | /* Drop initial reference. */ | 2625 | /* Drop initial reference. */ |
| 2492 | module_put(mod); | 2626 | module_put(mod); |
| 2493 | trim_init_extable(mod); | 2627 | trim_init_extable(mod); |
| 2628 | #ifdef CONFIG_KALLSYMS | ||
| 2629 | mod->num_symtab = mod->core_num_syms; | ||
| 2630 | mod->symtab = mod->core_symtab; | ||
| 2631 | mod->strtab = mod->core_strtab; | ||
| 2632 | #endif | ||
| 2494 | module_free(mod, mod->module_init); | 2633 | module_free(mod, mod->module_init); |
| 2495 | mod->module_init = NULL; | 2634 | mod->module_init = NULL; |
| 2496 | mod->init_size = 0; | 2635 | mod->init_size = 0; |
diff --git a/kernel/params.c b/kernel/params.c index 7f6912ced2ba..9da58eabdcb2 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/ctype.h> | ||
| 26 | 27 | ||
| 27 | #if 0 | 28 | #if 0 |
| 28 | #define DEBUGP printk | 29 | #define DEBUGP printk |
| @@ -87,7 +88,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | for (i = 0; args[i]; i++) { | 90 | for (i = 0; args[i]; i++) { |
| 90 | if (args[i] == ' ' && !in_quote) | 91 | if (isspace(args[i]) && !in_quote) |
| 91 | break; | 92 | break; |
| 92 | if (equals == 0) { | 93 | if (equals == 0) { |
| 93 | if (args[i] == '=') | 94 | if (args[i] == '=') |
| @@ -121,7 +122,7 @@ static char *next_arg(char *args, char **param, char **val) | |||
| 121 | next = args + i; | 122 | next = args + i; |
| 122 | 123 | ||
| 123 | /* Chew up trailing spaces. */ | 124 | /* Chew up trailing spaces. */ |
| 124 | while (*next == ' ') | 125 | while (isspace(*next)) |
| 125 | next++; | 126 | next++; |
| 126 | return next; | 127 | return next; |
| 127 | } | 128 | } |
| @@ -138,7 +139,7 @@ int parse_args(const char *name, | |||
| 138 | DEBUGP("Parsing ARGS: %s\n", args); | 139 | DEBUGP("Parsing ARGS: %s\n", args); |
| 139 | 140 | ||
| 140 | /* Chew leading spaces */ | 141 | /* Chew leading spaces */ |
| 141 | while (*args == ' ') | 142 | while (isspace(*args)) |
| 142 | args++; | 143 | args++; |
| 143 | 144 | ||
| 144 | while (*args) { | 145 | while (*args) { |
