[Devel,RHEL7,COMMIT] ms/module: keep percpu symbols in module's symtab

Submitted by Konstantin Khorenko on May 31, 2017, 1:36 p.m.

Details

Message ID 201705311336.v4VDaXnq018588@finist_cl7.x64_64.work.ct
State New
Series "ms/module: keep percpu symbols in module's symtab"
Headers show

Commit Message

Konstantin Khorenko May 31, 2017, 1:36 p.m.
The commit is pushed to "branch-rh7-3.10.0-514.16.1.vz7.32.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.16.1.vz7.32.5
------>
commit 2bc296330a409f1c8b66d9e3a77a945613718f82
Author: Miroslav Benes <mbenes@suse.cz>
Date:   Wed May 31 17:36:33 2017 +0400

    ms/module: keep percpu symbols in module's symtab
    
    ms commit: e0224418516b4d8a6c2160574bac18447c354ef0
    
    Currently, percpu symbols from .data..percpu ELF section of a module are
    not copied over and stored in final symtab array of struct module.
    Consequently such symbol cannot be returned via kallsyms API (for
    example kallsyms_lookup_name). This can be especially confusing when the
    percpu symbol is exported. Only its __ksymtab et al. are present in its
    symtab.
    
    The culprit is in layout_and_allocate() function where SHF_ALLOC flag is
    dropped for .data..percpu section. There is in fact no need to copy the
    section to final struct module, because kernel module loader allocates
    extra percpu section by itself. Unfortunately only symbols from
    SHF_ALLOC sections are copied due to a check in is_core_symbol().
    
    The patch changes is_core_symbol() function to copy over also percpu
    symbols (their st_shndx points to .data..percpu ELF section). We do it
    only if CONFIG_KALLSYMS_ALL is set to be consistent with the rest of the
    function (ELF section is SHF_ALLOC but !SHF_EXECINSTR). Finally
    elf_type() returns type 'a' for a percpu symbol because its address is
    absolute.
    
    Signed-off-by: Miroslav Benes <mbenes@suse.cz>
    Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
    Signed-off-by: Jiri Kosina <jkosina@suse.cz>
    
    The patch was selected in the scope of https://jira.sw.ru/browse/PSBM-66337.
    Without it, ReadyKernel patches cannot be prepared for the kernel modules,
    for example, ext4, if the changed code touches percpu variables defined in
    these modules.
    
    Signed-off-by: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
    Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 kernel/module.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/module.c b/kernel/module.c
index 82f9bbe..72af627 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2305,7 +2305,7 @@  static char elf_type(const Elf_Sym *sym, const struct load_info *info)
 	}
 	if (sym->st_shndx == SHN_UNDEF)
 		return 'U';
-	if (sym->st_shndx == SHN_ABS)
+	if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
 		return 'a';
 	if (sym->st_shndx >= SHN_LORESERVE)
 		return '?';
@@ -2334,7 +2334,7 @@  static char elf_type(const Elf_Sym *sym, const struct load_info *info)
 }
 
 static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
-                           unsigned int shnum)
+			   unsigned int shnum, unsigned int pcpundx)
 {
 	const Elf_Shdr *sec;
 
@@ -2343,6 +2343,11 @@  static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
 	    || !src->st_name)
 		return false;
 
+#ifdef CONFIG_KALLSYMS_ALL
+	if (src->st_shndx == pcpundx)
+		return true;
+#endif
+
 	sec = sechdrs + src->st_shndx;
 	if (!(sec->sh_flags & SHF_ALLOC)
 #ifndef CONFIG_KALLSYMS_ALL
@@ -2380,7 +2385,8 @@  static void layout_symtab(struct module *mod, struct load_info *info)
 	/* Compute total space required for the core symbols' strtab. */
 	for (ndst = i = 0; i < nsrc; i++) {
 		if (i == 0 ||
-		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
+				   info->index.pcpu)) {
 			strtab_size += strlen(&info->strtab[src[i].st_name])+1;
 			ndst++;
 		}
@@ -2420,7 +2426,8 @@  static void add_kallsyms(struct module *mod, const struct load_info *info)
 	src = mod->symtab;
 	for (ndst = i = 0; i < mod->num_symtab; i++) {
 		if (i == 0 ||
-		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
+				   info->index.pcpu)) {
 			dst[ndst] = src[i];
 			dst[ndst++].st_name = s - mod->core_strtab;
 			s += strlcpy(s, &mod->strtab[src[i].st_name],