diff options
| -rw-r--r-- | include/linux/module.h | 2 | ||||
| -rw-r--r-- | kernel/module.c | 68 |
2 files changed, 57 insertions, 13 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 1d3ccb173fd6..aca980365956 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -315,7 +315,7 @@ struct module | |||
| 315 | */ | 315 | */ |
| 316 | Elf_Sym *symtab, *core_symtab; | 316 | Elf_Sym *symtab, *core_symtab; |
| 317 | unsigned int num_symtab, core_num_syms; | 317 | unsigned int num_symtab, core_num_syms; |
| 318 | char *strtab; | 318 | char *strtab, *core_strtab; |
| 319 | 319 | ||
| 320 | /* Section attributes */ | 320 | /* Section attributes */ |
| 321 | struct module_sect_attrs *sect_attrs; | 321 | struct module_sect_attrs *sect_attrs; |
diff --git a/kernel/module.c b/kernel/module.c index 97f4d5e15535..39827c3d9484 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -1886,12 +1886,17 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, | |||
| 1886 | static unsigned long layout_symtab(struct module *mod, | 1886 | static unsigned long layout_symtab(struct module *mod, |
| 1887 | Elf_Shdr *sechdrs, | 1887 | Elf_Shdr *sechdrs, |
| 1888 | unsigned int symindex, | 1888 | unsigned int symindex, |
| 1889 | unsigned int strindex, | ||
| 1889 | const Elf_Ehdr *hdr, | 1890 | const Elf_Ehdr *hdr, |
| 1890 | const char *secstrings) | 1891 | const char *secstrings, |
| 1892 | unsigned long *pstroffs, | ||
| 1893 | unsigned long *strmap) | ||
| 1891 | { | 1894 | { |
| 1892 | unsigned long symoffs; | 1895 | unsigned long symoffs; |
| 1893 | Elf_Shdr *symsect = sechdrs + symindex; | 1896 | Elf_Shdr *symsect = sechdrs + symindex; |
| 1897 | Elf_Shdr *strsect = sechdrs + strindex; | ||
| 1894 | const Elf_Sym *src; | 1898 | const Elf_Sym *src; |
| 1899 | const char *strtab; | ||
| 1895 | unsigned int i, nsrc, ndst; | 1900 | unsigned int i, nsrc, ndst; |
| 1896 | 1901 | ||
| 1897 | /* Put symbol section at end of init part of module. */ | 1902 | /* Put symbol section at end of init part of module. */ |
| @@ -1902,14 +1907,31 @@ static unsigned long layout_symtab(struct module *mod, | |||
| 1902 | 1907 | ||
| 1903 | src = (void *)hdr + symsect->sh_offset; | 1908 | src = (void *)hdr + symsect->sh_offset; |
| 1904 | nsrc = symsect->sh_size / sizeof(*src); | 1909 | nsrc = symsect->sh_size / sizeof(*src); |
| 1910 | strtab = (void *)hdr + strsect->sh_offset; | ||
| 1905 | for (ndst = i = 1; i < nsrc; ++i, ++src) | 1911 | for (ndst = i = 1; i < nsrc; ++i, ++src) |
| 1906 | if (is_core_symbol(src, sechdrs, hdr->e_shnum)) | 1912 | if (is_core_symbol(src, sechdrs, hdr->e_shnum)) { |
| 1913 | unsigned int j = src->st_name; | ||
| 1914 | |||
| 1915 | while(!__test_and_set_bit(j, strmap) && strtab[j]) | ||
| 1916 | ++j; | ||
| 1907 | ++ndst; | 1917 | ++ndst; |
| 1918 | } | ||
| 1908 | 1919 | ||
| 1909 | /* Append room for core symbols at end of core part. */ | 1920 | /* Append room for core symbols at end of core part. */ |
| 1910 | symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); | 1921 | symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); |
| 1911 | mod->core_size = symoffs + ndst * sizeof(Elf_Sym); | 1922 | mod->core_size = symoffs + ndst * sizeof(Elf_Sym); |
| 1912 | 1923 | ||
| 1924 | /* Put string table section at end of init part of module. */ | ||
| 1925 | strsect->sh_flags |= SHF_ALLOC; | ||
| 1926 | strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect, | ||
| 1927 | strindex) | INIT_OFFSET_MASK; | ||
| 1928 | DEBUGP("\t%s\n", secstrings + strsect->sh_name); | ||
| 1929 | |||
| 1930 | /* Append room for core symbols' strings at end of core part. */ | ||
| 1931 | *pstroffs = mod->core_size; | ||
| 1932 | __set_bit(0, strmap); | ||
| 1933 | mod->core_size += bitmap_weight(strmap, strsect->sh_size); | ||
| 1934 | |||
| 1913 | return symoffs; | 1935 | return symoffs; |
| 1914 | } | 1936 | } |
| 1915 | 1937 | ||
| @@ -1919,11 +1941,14 @@ static void add_kallsyms(struct module *mod, | |||
| 1919 | unsigned int symindex, | 1941 | unsigned int symindex, |
| 1920 | unsigned int strindex, | 1942 | unsigned int strindex, |
| 1921 | unsigned long symoffs, | 1943 | unsigned long symoffs, |
| 1922 | const char *secstrings) | 1944 | unsigned long stroffs, |
| 1945 | const char *secstrings, | ||
| 1946 | unsigned long *strmap) | ||
| 1923 | { | 1947 | { |
| 1924 | unsigned int i, ndst; | 1948 | unsigned int i, ndst; |
| 1925 | const Elf_Sym *src; | 1949 | const Elf_Sym *src; |
| 1926 | Elf_Sym *dst; | 1950 | Elf_Sym *dst; |
| 1951 | char *s; | ||
| 1927 | 1952 | ||
| 1928 | mod->symtab = (void *)sechdrs[symindex].sh_addr; | 1953 | mod->symtab = (void *)sechdrs[symindex].sh_addr; |
| 1929 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); | 1954 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
| @@ -1941,16 +1966,25 @@ static void add_kallsyms(struct module *mod, | |||
| 1941 | if (!is_core_symbol(src, sechdrs, shnum)) | 1966 | if (!is_core_symbol(src, sechdrs, shnum)) |
| 1942 | continue; | 1967 | continue; |
| 1943 | dst[ndst] = *src; | 1968 | dst[ndst] = *src; |
| 1969 | dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); | ||
| 1944 | ++ndst; | 1970 | ++ndst; |
| 1945 | } | 1971 | } |
| 1946 | mod->core_num_syms = ndst; | 1972 | mod->core_num_syms = ndst; |
| 1973 | |||
| 1974 | mod->core_strtab = s = mod->module_core + stroffs; | ||
| 1975 | for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i) | ||
| 1976 | if (test_bit(i, strmap)) | ||
| 1977 | *++s = mod->strtab[i]; | ||
| 1947 | } | 1978 | } |
| 1948 | #else | 1979 | #else |
| 1949 | static inline unsigned long layout_symtab(struct module *mod, | 1980 | static inline unsigned long layout_symtab(struct module *mod, |
| 1950 | Elf_Shdr *sechdrs, | 1981 | Elf_Shdr *sechdrs, |
| 1951 | unsigned int symindex, | 1982 | unsigned int symindex, |
| 1983 | unsigned int strindex, | ||
| 1952 | const Elf_Hdr *hdr, | 1984 | const Elf_Hdr *hdr, |
| 1953 | const char *secstrings) | 1985 | const char *secstrings, |
| 1986 | unsigned long *pstroffs, | ||
| 1987 | unsigned long *strmap) | ||
| 1954 | { | 1988 | { |
| 1955 | } | 1989 | } |
| 1956 | static inline void add_kallsyms(struct module *mod, | 1990 | static inline void add_kallsyms(struct module *mod, |
| @@ -1959,7 +1993,9 @@ static inline void add_kallsyms(struct module *mod, | |||
| 1959 | unsigned int symindex, | 1993 | unsigned int symindex, |
| 1960 | unsigned int strindex, | 1994 | unsigned int strindex, |
| 1961 | unsigned long symoffs, | 1995 | unsigned long symoffs, |
| 1962 | const char *secstrings) | 1996 | unsigned long stroffs, |
| 1997 | const char *secstrings, | ||
| 1998 | const unsigned long *strmap) | ||
| 1963 | { | 1999 | { |
| 1964 | } | 2000 | } |
| 1965 | #endif /* CONFIG_KALLSYMS */ | 2001 | #endif /* CONFIG_KALLSYMS */ |
| @@ -2035,7 +2071,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2035 | long err = 0; | 2071 | long err = 0; |
| 2036 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 2072 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
| 2037 | #ifdef CONFIG_KALLSYMS | 2073 | #ifdef CONFIG_KALLSYMS |
| 2038 | unsigned long symoffs; | 2074 | unsigned long symoffs, stroffs, *strmap; |
| 2039 | #endif | 2075 | #endif |
| 2040 | mm_segment_t old_fs; | 2076 | mm_segment_t old_fs; |
| 2041 | 2077 | ||
| @@ -2118,10 +2154,6 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2118 | /* Don't keep modinfo and version sections. */ | 2154 | /* Don't keep modinfo and version sections. */ |
| 2119 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2155 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2120 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2156 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2121 | #ifdef CONFIG_KALLSYMS | ||
| 2122 | /* Keep string table for decoding later. */ | ||
| 2123 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | ||
| 2124 | #endif | ||
| 2125 | 2157 | ||
| 2126 | /* Check module struct version now, before we try to use module. */ | 2158 | /* Check module struct version now, before we try to use module. */ |
| 2127 | if (!check_modstruct_version(sechdrs, versindex, mod)) { | 2159 | if (!check_modstruct_version(sechdrs, versindex, mod)) { |
| @@ -2157,6 +2189,13 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2157 | goto free_hdr; | 2189 | goto free_hdr; |
| 2158 | } | 2190 | } |
| 2159 | 2191 | ||
| 2192 | strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size) | ||
| 2193 | * sizeof(long), GFP_KERNEL); | ||
| 2194 | if (!strmap) { | ||
| 2195 | err = -ENOMEM; | ||
| 2196 | goto free_mod; | ||
| 2197 | } | ||
| 2198 | |||
| 2160 | if (find_module(mod->name)) { | 2199 | if (find_module(mod->name)) { |
| 2161 | err = -EEXIST; | 2200 | err = -EEXIST; |
| 2162 | goto free_mod; | 2201 | goto free_mod; |
| @@ -2186,7 +2225,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2186 | this is done generically; there doesn't appear to be any | 2225 | this is done generically; there doesn't appear to be any |
| 2187 | special cases for the architectures. */ | 2226 | special cases for the architectures. */ |
| 2188 | layout_sections(mod, hdr, sechdrs, secstrings); | 2227 | layout_sections(mod, hdr, sechdrs, secstrings); |
| 2189 | symoffs = layout_symtab(mod, sechdrs, symindex, hdr, secstrings); | 2228 | symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr, |
| 2229 | secstrings, &stroffs, strmap); | ||
| 2190 | 2230 | ||
| 2191 | /* Do the allocs. */ | 2231 | /* Do the allocs. */ |
| 2192 | ptr = module_alloc_update_bounds(mod->core_size); | 2232 | ptr = module_alloc_update_bounds(mod->core_size); |
| @@ -2392,7 +2432,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2392 | sechdrs[pcpuindex].sh_size); | 2432 | sechdrs[pcpuindex].sh_size); |
| 2393 | 2433 | ||
| 2394 | add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, | 2434 | add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, |
| 2395 | symoffs, secstrings); | 2435 | symoffs, stroffs, secstrings, strmap); |
| 2436 | kfree(strmap); | ||
| 2437 | strmap = NULL; | ||
| 2396 | 2438 | ||
| 2397 | if (!mod->taints) { | 2439 | if (!mod->taints) { |
| 2398 | struct _ddebug *debug; | 2440 | struct _ddebug *debug; |
| @@ -2481,6 +2523,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2481 | percpu_modfree(percpu); | 2523 | percpu_modfree(percpu); |
| 2482 | free_mod: | 2524 | free_mod: |
| 2483 | kfree(args); | 2525 | kfree(args); |
| 2526 | kfree(strmap); | ||
| 2484 | free_hdr: | 2527 | free_hdr: |
| 2485 | vfree(hdr); | 2528 | vfree(hdr); |
| 2486 | return ERR_PTR(err); | 2529 | return ERR_PTR(err); |
| @@ -2573,6 +2616,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2573 | #ifdef CONFIG_KALLSYMS | 2616 | #ifdef CONFIG_KALLSYMS |
| 2574 | mod->num_symtab = mod->core_num_syms; | 2617 | mod->num_symtab = mod->core_num_syms; |
| 2575 | mod->symtab = mod->core_symtab; | 2618 | mod->symtab = mod->core_symtab; |
| 2619 | mod->strtab = mod->core_strtab; | ||
| 2576 | #endif | 2620 | #endif |
| 2577 | module_free(mod, mod->module_init); | 2621 | module_free(mod, mod->module_init); |
| 2578 | mod->module_init = NULL; | 2622 | mod->module_init = NULL; |
