Loading kernel/module.c +29 −39 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,16 @@ int unregister_module_notifier(struct notifier_block * nb) } } EXPORT_SYMBOL(unregister_module_notifier); EXPORT_SYMBOL(unregister_module_notifier); struct load_info { Elf_Ehdr *hdr; unsigned long len; Elf_Shdr *sechdrs; char *secstrings, *args, *strtab; struct { unsigned int sym, str, mod, vers, info, pcpu; } index; }; /* We require a truly strong try_module_get(): 0 means failure due to /* We require a truly strong try_module_get(): 0 means failure due to ongoing or failed initialization etc. */ ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) static inline int strong_try_module_get(struct module *mod) Loading Loading @@ -1909,11 +1919,10 @@ static int is_exported(const char *name, unsigned long value, } } /* As per nm */ /* As per nm */ static char elf_type(const Elf_Sym *sym, static char elf_type(const Elf_Sym *sym, const struct load_info *info) Elf_Shdr *sechdrs, const char *secstrings, struct module *mod) { { const Elf_Shdr *sechdrs = info->sechdrs; if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) return 'v'; return 'v'; Loading Loading @@ -1943,8 +1952,10 @@ static char elf_type(const Elf_Sym *sym, else else return 'b'; return 'b'; } } if (strstarts(secstrings + sechdrs[sym->st_shndx].sh_name, ".debug")) if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name, ".debug")) { return 'n'; return 'n'; } return '?'; return '?'; } } Loading Loading @@ -2021,35 +2032,30 @@ static unsigned long layout_symtab(struct module *mod, return symoffs; return symoffs; } } static void add_kallsyms(struct module *mod, static void add_kallsyms(struct module *mod, struct load_info *info, Elf_Shdr *sechdrs, unsigned int shnum, unsigned int symindex, unsigned int strindex, unsigned long symoffs, unsigned long symoffs, unsigned long stroffs, unsigned long stroffs, const char *secstrings, unsigned long *strmap) unsigned long *strmap) { { unsigned int i, ndst; unsigned int i, ndst; const Elf_Sym *src; const Elf_Sym *src; Elf_Sym *dst; Elf_Sym *dst; char *s; char *s; Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; mod->symtab = (void *)sechdrs[symindex].sh_addr; mod->symtab = (void *)symsec->sh_addr; mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym); mod->strtab = (void *)sechdrs[strindex].sh_addr; mod->strtab = info->strtab; /* Set types up while we still have access to sections. */ /* Set types up while we still have access to sections. */ for (i = 0; i < mod->num_symtab; i++) for (i = 0; i < mod->num_symtab; i++) mod->symtab[i].st_info mod->symtab[i].st_info = elf_type(&mod->symtab[i], info); = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); mod->core_symtab = dst = mod->module_core + symoffs; mod->core_symtab = dst = mod->module_core + symoffs; src = mod->symtab; src = mod->symtab; *dst = *src; *dst = *src; for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { if (!is_core_symbol(src, sechdrs, shnum)) if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) continue; continue; dst[ndst] = *src; dst[ndst] = *src; dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); Loading @@ -2058,7 +2064,7 @@ static void add_kallsyms(struct module *mod, mod->core_num_syms = ndst; mod->core_num_syms = ndst; mod->core_strtab = s = mod->module_core + stroffs; mod->core_strtab = s = mod->module_core + stroffs; for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i) for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i) if (test_bit(i, strmap)) if (test_bit(i, strmap)) *++s = mod->strtab[i]; *++s = mod->strtab[i]; } } Loading @@ -2075,15 +2081,10 @@ static inline unsigned long layout_symtab(struct module *mod, return 0; return 0; } } static inline void add_kallsyms(struct module *mod, static void add_kallsyms(struct module *mod, struct load_info *info, Elf_Shdr *sechdrs, unsigned int shnum, unsigned int symindex, unsigned int strindex, unsigned long symoffs, unsigned long symoffs, unsigned long stroffs, unsigned long stroffs, const char *secstrings, unsigned long *strmap) const unsigned long *strmap) { { } } #endif /* CONFIG_KALLSYMS */ #endif /* CONFIG_KALLSYMS */ Loading Loading @@ -2148,16 +2149,6 @@ static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, } } #endif #endif struct load_info { Elf_Ehdr *hdr; unsigned long len; Elf_Shdr *sechdrs; char *secstrings, *args, *strtab; struct { unsigned int sym, str, mod, vers, info, pcpu; } index; }; /* Sets info->hdr and info->len. */ /* Sets info->hdr and info->len. */ static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len) static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len) { { Loading Loading @@ -2623,8 +2614,7 @@ static noinline struct module *load_module(void __user *umod, percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr, percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr, info.sechdrs[info.index.pcpu].sh_size); info.sechdrs[info.index.pcpu].sh_size); add_kallsyms(mod, info.sechdrs, info.hdr->e_shnum, info.index.sym, info.index.str, add_kallsyms(mod, &info, symoffs, stroffs, strmap); symoffs, stroffs, info.secstrings, strmap); kfree(strmap); kfree(strmap); strmap = NULL; strmap = NULL; Loading Loading
kernel/module.c +29 −39 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,16 @@ int unregister_module_notifier(struct notifier_block * nb) } } EXPORT_SYMBOL(unregister_module_notifier); EXPORT_SYMBOL(unregister_module_notifier); struct load_info { Elf_Ehdr *hdr; unsigned long len; Elf_Shdr *sechdrs; char *secstrings, *args, *strtab; struct { unsigned int sym, str, mod, vers, info, pcpu; } index; }; /* We require a truly strong try_module_get(): 0 means failure due to /* We require a truly strong try_module_get(): 0 means failure due to ongoing or failed initialization etc. */ ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) static inline int strong_try_module_get(struct module *mod) Loading Loading @@ -1909,11 +1919,10 @@ static int is_exported(const char *name, unsigned long value, } } /* As per nm */ /* As per nm */ static char elf_type(const Elf_Sym *sym, static char elf_type(const Elf_Sym *sym, const struct load_info *info) Elf_Shdr *sechdrs, const char *secstrings, struct module *mod) { { const Elf_Shdr *sechdrs = info->sechdrs; if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) return 'v'; return 'v'; Loading Loading @@ -1943,8 +1952,10 @@ static char elf_type(const Elf_Sym *sym, else else return 'b'; return 'b'; } } if (strstarts(secstrings + sechdrs[sym->st_shndx].sh_name, ".debug")) if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name, ".debug")) { return 'n'; return 'n'; } return '?'; return '?'; } } Loading Loading @@ -2021,35 +2032,30 @@ static unsigned long layout_symtab(struct module *mod, return symoffs; return symoffs; } } static void add_kallsyms(struct module *mod, static void add_kallsyms(struct module *mod, struct load_info *info, Elf_Shdr *sechdrs, unsigned int shnum, unsigned int symindex, unsigned int strindex, unsigned long symoffs, unsigned long symoffs, unsigned long stroffs, unsigned long stroffs, const char *secstrings, unsigned long *strmap) unsigned long *strmap) { { unsigned int i, ndst; unsigned int i, ndst; const Elf_Sym *src; const Elf_Sym *src; Elf_Sym *dst; Elf_Sym *dst; char *s; char *s; Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; mod->symtab = (void *)sechdrs[symindex].sh_addr; mod->symtab = (void *)symsec->sh_addr; mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym); mod->strtab = (void *)sechdrs[strindex].sh_addr; mod->strtab = info->strtab; /* Set types up while we still have access to sections. */ /* Set types up while we still have access to sections. */ for (i = 0; i < mod->num_symtab; i++) for (i = 0; i < mod->num_symtab; i++) mod->symtab[i].st_info mod->symtab[i].st_info = elf_type(&mod->symtab[i], info); = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); mod->core_symtab = dst = mod->module_core + symoffs; mod->core_symtab = dst = mod->module_core + symoffs; src = mod->symtab; src = mod->symtab; *dst = *src; *dst = *src; for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { if (!is_core_symbol(src, sechdrs, shnum)) if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) continue; continue; dst[ndst] = *src; dst[ndst] = *src; dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name); Loading @@ -2058,7 +2064,7 @@ static void add_kallsyms(struct module *mod, mod->core_num_syms = ndst; mod->core_num_syms = ndst; mod->core_strtab = s = mod->module_core + stroffs; mod->core_strtab = s = mod->module_core + stroffs; for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i) for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i) if (test_bit(i, strmap)) if (test_bit(i, strmap)) *++s = mod->strtab[i]; *++s = mod->strtab[i]; } } Loading @@ -2075,15 +2081,10 @@ static inline unsigned long layout_symtab(struct module *mod, return 0; return 0; } } static inline void add_kallsyms(struct module *mod, static void add_kallsyms(struct module *mod, struct load_info *info, Elf_Shdr *sechdrs, unsigned int shnum, unsigned int symindex, unsigned int strindex, unsigned long symoffs, unsigned long symoffs, unsigned long stroffs, unsigned long stroffs, const char *secstrings, unsigned long *strmap) const unsigned long *strmap) { { } } #endif /* CONFIG_KALLSYMS */ #endif /* CONFIG_KALLSYMS */ Loading Loading @@ -2148,16 +2149,6 @@ static inline void kmemleak_load_module(struct module *mod, Elf_Ehdr *hdr, } } #endif #endif struct load_info { Elf_Ehdr *hdr; unsigned long len; Elf_Shdr *sechdrs; char *secstrings, *args, *strtab; struct { unsigned int sym, str, mod, vers, info, pcpu; } index; }; /* Sets info->hdr and info->len. */ /* Sets info->hdr and info->len. */ static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len) static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len) { { Loading Loading @@ -2623,8 +2614,7 @@ static noinline struct module *load_module(void __user *umod, percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr, percpu_modcopy(mod, (void *)info.sechdrs[info.index.pcpu].sh_addr, info.sechdrs[info.index.pcpu].sh_size); info.sechdrs[info.index.pcpu].sh_size); add_kallsyms(mod, info.sechdrs, info.hdr->e_shnum, info.index.sym, info.index.str, add_kallsyms(mod, &info, symoffs, stroffs, strmap); symoffs, stroffs, info.secstrings, strmap); kfree(strmap); kfree(strmap); strmap = NULL; strmap = NULL; Loading