diff options
| -rw-r--r-- | include/linux/module.h | 10 | ||||
| -rw-r--r-- | kernel/module.c | 91 |
2 files changed, 94 insertions, 7 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 1c755b2f937d..1d3ccb173fd6 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -308,9 +308,13 @@ struct module | |||
| 308 | #endif | 308 | #endif |
| 309 | 309 | ||
| 310 | #ifdef CONFIG_KALLSYMS | 310 | #ifdef CONFIG_KALLSYMS |
| 311 | /* We keep the symbol and string tables for kallsyms. */ | 311 | /* |
| 312 | Elf_Sym *symtab; | 312 | * We keep the symbol and string tables for kallsyms. |
| 313 | unsigned int num_symtab; | 313 | * The core_* fields below are temporary, loader-only (they |
| 314 | * could really be discarded after module init). | ||
| 315 | */ | ||
| 316 | Elf_Sym *symtab, *core_symtab; | ||
| 317 | unsigned int num_symtab, core_num_syms; | ||
| 314 | char *strtab; | 318 | char *strtab; |
| 315 | 319 | ||
| 316 | /* Section attributes */ | 320 | /* Section attributes */ |
diff --git a/kernel/module.c b/kernel/module.c index e6bc4b28aa62..97f4d5e15535 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -1862,13 +1862,68 @@ static char elf_type(const Elf_Sym *sym, | |||
| 1862 | return '?'; | 1862 | return '?'; |
| 1863 | } | 1863 | } |
| 1864 | 1864 | ||
| 1865 | static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, | ||
| 1866 | unsigned int shnum) | ||
| 1867 | { | ||
| 1868 | const Elf_Shdr *sec; | ||
| 1869 | |||
| 1870 | if (src->st_shndx == SHN_UNDEF | ||
| 1871 | || src->st_shndx >= shnum | ||
| 1872 | || !src->st_name) | ||
| 1873 | return false; | ||
| 1874 | |||
| 1875 | sec = sechdrs + src->st_shndx; | ||
| 1876 | if (!(sec->sh_flags & SHF_ALLOC) | ||
| 1877 | #ifndef CONFIG_KALLSYMS_ALL | ||
| 1878 | || !(sec->sh_flags & SHF_EXECINSTR) | ||
| 1879 | #endif | ||
| 1880 | || (sec->sh_entsize & INIT_OFFSET_MASK)) | ||
| 1881 | return false; | ||
| 1882 | |||
| 1883 | return true; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | static unsigned long layout_symtab(struct module *mod, | ||
| 1887 | Elf_Shdr *sechdrs, | ||
| 1888 | unsigned int symindex, | ||
| 1889 | const Elf_Ehdr *hdr, | ||
| 1890 | const char *secstrings) | ||
| 1891 | { | ||
| 1892 | unsigned long symoffs; | ||
| 1893 | Elf_Shdr *symsect = sechdrs + symindex; | ||
| 1894 | const Elf_Sym *src; | ||
| 1895 | unsigned int i, nsrc, ndst; | ||
| 1896 | |||
| 1897 | /* Put symbol section at end of init part of module. */ | ||
| 1898 | symsect->sh_flags |= SHF_ALLOC; | ||
| 1899 | symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect, | ||
| 1900 | symindex) | INIT_OFFSET_MASK; | ||
| 1901 | DEBUGP("\t%s\n", secstrings + symsect->sh_name); | ||
| 1902 | |||
| 1903 | src = (void *)hdr + symsect->sh_offset; | ||
| 1904 | nsrc = symsect->sh_size / sizeof(*src); | ||
| 1905 | for (ndst = i = 1; i < nsrc; ++i, ++src) | ||
| 1906 | if (is_core_symbol(src, sechdrs, hdr->e_shnum)) | ||
| 1907 | ++ndst; | ||
| 1908 | |||
| 1909 | /* Append room for core symbols at end of core part. */ | ||
| 1910 | symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); | ||
| 1911 | mod->core_size = symoffs + ndst * sizeof(Elf_Sym); | ||
| 1912 | |||
| 1913 | return symoffs; | ||
| 1914 | } | ||
| 1915 | |||
| 1865 | static void add_kallsyms(struct module *mod, | 1916 | static void add_kallsyms(struct module *mod, |
| 1866 | Elf_Shdr *sechdrs, | 1917 | Elf_Shdr *sechdrs, |
| 1918 | unsigned int shnum, | ||
| 1867 | unsigned int symindex, | 1919 | unsigned int symindex, |
| 1868 | unsigned int strindex, | 1920 | unsigned int strindex, |
| 1921 | unsigned long symoffs, | ||
| 1869 | const char *secstrings) | 1922 | const char *secstrings) |
| 1870 | { | 1923 | { |
| 1871 | unsigned int i; | 1924 | unsigned int i, ndst; |
| 1925 | const Elf_Sym *src; | ||
| 1926 | Elf_Sym *dst; | ||
| 1872 | 1927 | ||
| 1873 | mod->symtab = (void *)sechdrs[symindex].sh_addr; | 1928 | mod->symtab = (void *)sechdrs[symindex].sh_addr; |
| 1874 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); | 1929 | mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
| @@ -1878,12 +1933,32 @@ static void add_kallsyms(struct module *mod, | |||
| 1878 | for (i = 0; i < mod->num_symtab; i++) | 1933 | for (i = 0; i < mod->num_symtab; i++) |
| 1879 | mod->symtab[i].st_info | 1934 | mod->symtab[i].st_info |
| 1880 | = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); | 1935 | = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); |
| 1936 | |||
| 1937 | mod->core_symtab = dst = mod->module_core + symoffs; | ||
| 1938 | src = mod->symtab; | ||
| 1939 | *dst = *src; | ||
| 1940 | for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { | ||
| 1941 | if (!is_core_symbol(src, sechdrs, shnum)) | ||
| 1942 | continue; | ||
| 1943 | dst[ndst] = *src; | ||
| 1944 | ++ndst; | ||
| 1945 | } | ||
| 1946 | mod->core_num_syms = ndst; | ||
| 1881 | } | 1947 | } |
| 1882 | #else | 1948 | #else |
| 1949 | static inline unsigned long layout_symtab(struct module *mod, | ||
| 1950 | Elf_Shdr *sechdrs, | ||
| 1951 | unsigned int symindex, | ||
| 1952 | const Elf_Hdr *hdr, | ||
| 1953 | const char *secstrings) | ||
| 1954 | { | ||
| 1955 | } | ||
| 1883 | static inline void add_kallsyms(struct module *mod, | 1956 | static inline void add_kallsyms(struct module *mod, |
| 1884 | Elf_Shdr *sechdrs, | 1957 | Elf_Shdr *sechdrs, |
| 1958 | unsigned int shnum, | ||
| 1885 | unsigned int symindex, | 1959 | unsigned int symindex, |
| 1886 | unsigned int strindex, | 1960 | unsigned int strindex, |
| 1961 | unsigned long symoffs, | ||
| 1887 | const char *secstrings) | 1962 | const char *secstrings) |
| 1888 | { | 1963 | { |
| 1889 | } | 1964 | } |
| @@ -1959,6 +2034,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 1959 | struct module *mod; | 2034 | struct module *mod; |
| 1960 | long err = 0; | 2035 | long err = 0; |
| 1961 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 2036 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
| 2037 | #ifdef CONFIG_KALLSYMS | ||
| 2038 | unsigned long symoffs; | ||
| 2039 | #endif | ||
| 1962 | mm_segment_t old_fs; | 2040 | mm_segment_t old_fs; |
| 1963 | 2041 | ||
| 1964 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", | 2042 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
| @@ -2041,8 +2119,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2041 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2119 | sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2042 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2120 | sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2043 | #ifdef CONFIG_KALLSYMS | 2121 | #ifdef CONFIG_KALLSYMS |
| 2044 | /* Keep symbol and string tables for decoding later. */ | 2122 | /* Keep string table for decoding later. */ |
| 2045 | sechdrs[symindex].sh_flags |= SHF_ALLOC; | ||
| 2046 | sechdrs[strindex].sh_flags |= SHF_ALLOC; | 2123 | sechdrs[strindex].sh_flags |= SHF_ALLOC; |
| 2047 | #endif | 2124 | #endif |
| 2048 | 2125 | ||
| @@ -2109,6 +2186,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2109 | this is done generically; there doesn't appear to be any | 2186 | this is done generically; there doesn't appear to be any |
| 2110 | special cases for the architectures. */ | 2187 | special cases for the architectures. */ |
| 2111 | layout_sections(mod, hdr, sechdrs, secstrings); | 2188 | layout_sections(mod, hdr, sechdrs, secstrings); |
| 2189 | symoffs = layout_symtab(mod, sechdrs, symindex, hdr, secstrings); | ||
| 2112 | 2190 | ||
| 2113 | /* Do the allocs. */ | 2191 | /* Do the allocs. */ |
| 2114 | ptr = module_alloc_update_bounds(mod->core_size); | 2192 | ptr = module_alloc_update_bounds(mod->core_size); |
| @@ -2313,7 +2391,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2313 | percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, | 2391 | percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, |
| 2314 | sechdrs[pcpuindex].sh_size); | 2392 | sechdrs[pcpuindex].sh_size); |
| 2315 | 2393 | ||
| 2316 | add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); | 2394 | add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, |
| 2395 | symoffs, secstrings); | ||
| 2317 | 2396 | ||
| 2318 | if (!mod->taints) { | 2397 | if (!mod->taints) { |
| 2319 | struct _ddebug *debug; | 2398 | struct _ddebug *debug; |
| @@ -2491,6 +2570,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2491 | /* Drop initial reference. */ | 2570 | /* Drop initial reference. */ |
| 2492 | module_put(mod); | 2571 | module_put(mod); |
| 2493 | trim_init_extable(mod); | 2572 | trim_init_extable(mod); |
| 2573 | #ifdef CONFIG_KALLSYMS | ||
| 2574 | mod->num_symtab = mod->core_num_syms; | ||
| 2575 | mod->symtab = mod->core_symtab; | ||
| 2576 | #endif | ||
| 2494 | module_free(mod, mod->module_init); | 2577 | module_free(mod, mod->module_init); |
| 2495 | mod->module_init = NULL; | 2578 | mod->module_init = NULL; |
| 2496 | mod->init_size = 0; | 2579 | mod->init_size = 0; |
