[PATCH v1] module/kallsyms: Filter out local mapping symbols during module load

Tiezhu Yang posted 1 patch 1 month, 3 weeks ago
There is a newer version of this series
kernel/module/kallsyms.c | 7 +++++++
1 file changed, 7 insertions(+)
[PATCH v1] module/kallsyms: Filter out local mapping symbols during module load
Posted by Tiezhu Yang 1 month, 3 weeks ago
The compiler toolchains generate internal local labels on certain
architectures (such as LoongArch) for optimizations and relocations.

While these local labels are filtered out during runtime lookups in
find_kallsyms_symbol(), they still leak into the permanent symbol
tables of loaded modules, because layout_symtab() and add_kallsyms()
do not check for the mapping symbols during layout generation.

Consequently, tracing tools like bpftrace resolve identical addresses
into confusing local labels instead of actual clear C function names.

Fix this by adding is_mapping_symbol() checks directly into the symbol
tracking loops of layout_symtab() and add_kallsyms(). This prevents the
mapping symbols from entering the module's memory symbol arrays at load
time.

Reproduce steps:

1. Set up a LoongArch VM with "-accel kvm":

   $ sudo qemu-system-loongarch64 -serial stdio \
     -machine virt -cpu la464 -smp 4 -m 4G \
     -bios /usr/share/edk2/loongarch64/QEMU_EFI.fd \
     -nodefaults -no-reboot -nographic -accel kvm

2. Use bpftrace to capture kstack when vCPU is scheduled out:

   $ cat trace_sched.bt
   kprobe:kvm:kvm_sched_out
   {
           if (pid == $1) {
                   print(kstack());
           }
   }

   $ sudo bpftrace trace_sched.bt `pgrep -o qemu-system`

Test results:

1. Before this patch (Confusing stack with local labels):

        kvm_sched_out+0
        __schedule+1584
        schedule+48
        .LVL3767+36
        .LVL3801+8
        .LVL285+12
        .LVL425+44
        .LVL1419+20
        kvm_exc_entry+260

2. After this patch (Accurate stack with function names):

        kvm_sched_out+0
        __schedule+1584
        schedule+48
        kvm_vcpu_block+112
        kvm_vcpu_halt+104
        kvm_emu_idle+284
        kvm_handle_gspr+1316
        kvm_handle_exit+456
        kvm_exc_entry+260

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
Based on the latest modules-next branch of
https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git

 kernel/module/kallsyms.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
index f23126d804b2..61dd5c014a59 100644
--- a/kernel/module/kallsyms.c
+++ b/kernel/module/kallsyms.c
@@ -130,6 +130,9 @@ 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 (is_mapping_symbol(&info->strtab[src[i].st_name]))
+			continue;
+
 		if (i == 0 || is_livepatch_module(mod) ||
 		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
 				   info->index.pcpu)) {
@@ -198,6 +201,10 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
 	src = kallsyms->symtab;
 	for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
 		kallsyms->typetab[i] = elf_type(src + i, info);
+
+		if (is_mapping_symbol(&kallsyms->strtab[src[i].st_name]))
+			continue;
+
 		if (i == 0 || is_livepatch_module(mod) ||
 		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
 				   info->index.pcpu)) {
-- 
2.42.0
Re: [PATCH v1] module/kallsyms: Filter out local mapping symbols during module load
Posted by Tiezhu Yang 1 month, 2 weeks ago
On 2026/8/8 上午11:37, Tiezhu Yang wrote:
> The compiler toolchains generate internal local labels on certain
> architectures (such as LoongArch) for optimizations and relocations.

...

> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
> Based on the latest modules-next branch of
> https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
> 
>   kernel/module/kallsyms.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
> index f23126d804b2..61dd5c014a59 100644
> --- a/kernel/module/kallsyms.c
> +++ b/kernel/module/kallsyms.c
> @@ -130,6 +130,9 @@ 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 (is_mapping_symbol(&info->strtab[src[i].st_name]))
> +			continue;
> +
>   		if (i == 0 || is_livepatch_module(mod) ||
>   		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
>   				   info->index.pcpu)) {
> @@ -198,6 +201,10 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
>   	src = kallsyms->symtab;
>   	for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
>   		kallsyms->typetab[i] = elf_type(src + i, info);
> +
> +		if (is_mapping_symbol(&kallsyms->strtab[src[i].st_name]))
> +			continue;
> +
>   		if (i == 0 || is_livepatch_module(mod) ||
>   		    is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
>   				   info->index.pcpu)) {
> 

Hi module maintainers,

Regarding the feedback from the AI bot about livepatch breaking [1],
there are two ways to fix it, which style do you prefer?

(1) Using continue

```
diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
index f23126d804b2..aece7aa49dd4 100644
--- a/kernel/module/kallsyms.c
+++ b/kernel/module/kallsyms.c
@@ -130,6 +130,10 @@ 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 (!is_livepatch_module(mod) &&
+                   is_mapping_symbol(&info->strtab[src[i].st_name]))
+                       continue;
+
                 if (i == 0 || is_livepatch_module(mod) ||
                     is_core_symbol(src + i, info->sechdrs, 
info->hdr->e_shnum,
                                    info->index.pcpu)) {
@@ -198,6 +202,11 @@ void add_kallsyms(struct module *mod, const struct 
load_info *info)
         src = kallsyms->symtab;
         for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
                 kallsyms->typetab[i] = elf_type(src + i, info);
+
+               if (!is_livepatch_module(mod) &&
+                   is_mapping_symbol(&kallsyms->strtab[src[i].st_name]))
+                       continue;
+
                 if (i == 0 || is_livepatch_module(mod) ||
                     is_core_symbol(src + i, info->sechdrs, 
info->hdr->e_shnum,
                                    info->index.pcpu)) {
```

(2) Using if-statement
```
diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
index f23126d804b2..b2b22b3487a8 100644
--- a/kernel/module/kallsyms.c
+++ b/kernel/module/kallsyms.c
@@ -130,9 +130,12 @@ 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_livepatch_module(mod) ||
+               bool is_mapping = !is_livepatch_module(mod) &&
+ 
is_mapping_symbol(&info->strtab[src[i].st_name]);
+
+               if (!is_mapping && (i == 0 || is_livepatch_module(mod) ||
                     is_core_symbol(src + i, info->sechdrs, 
info->hdr->e_shnum,
-                                  info->index.pcpu)) {
+                                  info->index.pcpu))) {
                         strtab_size += 
strlen(&info->strtab[src[i].st_name]) + 1;
                         ndst++;
                 }
@@ -198,9 +201,13 @@ void add_kallsyms(struct module *mod, const struct 
load_info *info)
         src = kallsyms->symtab;
         for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
                 kallsyms->typetab[i] = elf_type(src + i, info);
-               if (i == 0 || is_livepatch_module(mod) ||
+
+               bool is_mapping = !is_livepatch_module(mod) &&
+ 
is_mapping_symbol(&kallsyms->strtab[src[i].st_name]);
+
+               if (!is_mapping && (i == 0 || is_livepatch_module(mod) ||
                     is_core_symbol(src + i, info->sechdrs, 
info->hdr->e_shnum,
-                                  info->index.pcpu)) {
+                                  info->index.pcpu))) {
                         ssize_t ret;

                         mod->core_kallsyms.typetab[ndst] =
```

If you have any more comments, please let me know.

[1] 
https://lore.kernel.org/linux-modules/20260808035301.C3E6F1F000E9@smtp.kernel.org/

Thanks,
Tiezhu

Re: [PATCH v1] module/kallsyms: Filter out local mapping symbols during module load
Posted by Huacai Chen 1 month, 2 weeks ago
Hi, Tiezhu,

On Mon, Aug 10, 2026 at 10:07 AM Tiezhu Yang <yangtiezhu@loongson.cn> wrote:
>
> On 2026/8/8 上午11:37, Tiezhu Yang wrote:
> > The compiler toolchains generate internal local labels on certain
> > architectures (such as LoongArch) for optimizations and relocations.
>
> ...
>
> > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> > ---
> > Based on the latest modules-next branch of
> > https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
> >
> >   kernel/module/kallsyms.c | 7 +++++++
> >   1 file changed, 7 insertions(+)
> >
> > diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
> > index f23126d804b2..61dd5c014a59 100644
> > --- a/kernel/module/kallsyms.c
> > +++ b/kernel/module/kallsyms.c
> > @@ -130,6 +130,9 @@ 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 (is_mapping_symbol(&info->strtab[src[i].st_name]))
> > +                     continue;
> > +
> >               if (i == 0 || is_livepatch_module(mod) ||
> >                   is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
> >                                  info->index.pcpu)) {
> > @@ -198,6 +201,10 @@ void add_kallsyms(struct module *mod, const struct load_info *info)
> >       src = kallsyms->symtab;
> >       for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
> >               kallsyms->typetab[i] = elf_type(src + i, info);
> > +
> > +             if (is_mapping_symbol(&kallsyms->strtab[src[i].st_name]))
> > +                     continue;
> > +
> >               if (i == 0 || is_livepatch_module(mod) ||
> >                   is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
> >                                  info->index.pcpu)) {
> >
>
> Hi module maintainers,
>
> Regarding the feedback from the AI bot about livepatch breaking [1],
> there are two ways to fix it, which style do you prefer?
I think the first is better.


Huacai
>
> (1) Using continue
>
> ```
> diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
> index f23126d804b2..aece7aa49dd4 100644
> --- a/kernel/module/kallsyms.c
> +++ b/kernel/module/kallsyms.c
> @@ -130,6 +130,10 @@ 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 (!is_livepatch_module(mod) &&
> +                   is_mapping_symbol(&info->strtab[src[i].st_name]))
> +                       continue;
> +
>                  if (i == 0 || is_livepatch_module(mod) ||
>                      is_core_symbol(src + i, info->sechdrs,
> info->hdr->e_shnum,
>                                     info->index.pcpu)) {
> @@ -198,6 +202,11 @@ void add_kallsyms(struct module *mod, const struct
> load_info *info)
>          src = kallsyms->symtab;
>          for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
>                  kallsyms->typetab[i] = elf_type(src + i, info);
> +
> +               if (!is_livepatch_module(mod) &&
> +                   is_mapping_symbol(&kallsyms->strtab[src[i].st_name]))
> +                       continue;
> +
>                  if (i == 0 || is_livepatch_module(mod) ||
>                      is_core_symbol(src + i, info->sechdrs,
> info->hdr->e_shnum,
>                                     info->index.pcpu)) {
> ```
>
> (2) Using if-statement
> ```
> diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
> index f23126d804b2..b2b22b3487a8 100644
> --- a/kernel/module/kallsyms.c
> +++ b/kernel/module/kallsyms.c
> @@ -130,9 +130,12 @@ 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_livepatch_module(mod) ||
> +               bool is_mapping = !is_livepatch_module(mod) &&
> +
> is_mapping_symbol(&info->strtab[src[i].st_name]);
> +
> +               if (!is_mapping && (i == 0 || is_livepatch_module(mod) ||
>                      is_core_symbol(src + i, info->sechdrs,
> info->hdr->e_shnum,
> -                                  info->index.pcpu)) {
> +                                  info->index.pcpu))) {
>                          strtab_size +=
> strlen(&info->strtab[src[i].st_name]) + 1;
>                          ndst++;
>                  }
> @@ -198,9 +201,13 @@ void add_kallsyms(struct module *mod, const struct
> load_info *info)
>          src = kallsyms->symtab;
>          for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
>                  kallsyms->typetab[i] = elf_type(src + i, info);
> -               if (i == 0 || is_livepatch_module(mod) ||
> +
> +               bool is_mapping = !is_livepatch_module(mod) &&
> +
> is_mapping_symbol(&kallsyms->strtab[src[i].st_name]);
> +
> +               if (!is_mapping && (i == 0 || is_livepatch_module(mod) ||
>                      is_core_symbol(src + i, info->sechdrs,
> info->hdr->e_shnum,
> -                                  info->index.pcpu)) {
> +                                  info->index.pcpu))) {
>                          ssize_t ret;
>
>                          mod->core_kallsyms.typetab[ndst] =
> ```
>
> If you have any more comments, please let me know.
>
> [1]
> https://lore.kernel.org/linux-modules/20260808035301.C3E6F1F000E9@smtp.kernel.org/
>
> Thanks,
> Tiezhu
>
>