From d94e516c13eb6404117e8ba64aa423e651e1d6e9 Mon Sep 17 00:00:00 2001 From: Sumanth Korikkar Date: Tue, 10 Feb 2026 05:18:17 +0100 Subject: [PATCH] create-diff-object: Remove undefined function symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building shadow-pid.patch on a debug kernel, it generates __bug_table, which contains an array of struct bug_entries. .rela__bug_table contains references to bug address, line number and column. create-diff-object identifies that .text.kernel_clone has changed and it includes .rela.text.kernel_clone rela section. Then later, it includes all symbols (in kpatch_include_symbols()) associated with it, which ends up including __bug_table and its rela section .rela__bug_table. Then, all the function symbols associated with .rela__bug_table is included irrespective of whether it's section is included or not. This leads to the following modpost errors: kernel/fork.o: changed function: kernel_clone kernel/exit.o: changed function: do_exit fs/proc/array.o: changed function: proc_pid_status make -C /root/linux M=/root/.kpatch/tmp/patch CFLAGS_MODULE='' make[1]: Entering directory '/root/linux' make[2]: Entering directory '/root/.kpatch/tmp/patch' LDS kpatch.lds CC [M] patch-hook.o LD [M] test-shadow-newpid.o MODPOST Module.symvers WARNING: modpost: missing MODULE_DESCRIPTION() in test-shadow-newpid.o ERROR: modpost: "replace_mm_exe_file" [test-shadow-newpid.ko] undefined! ERROR: modpost: "put_task_stack" [test-shadow-newpid.ko] undefined! ERROR: modpost: "release_task" [test-shadow-newpid.ko] undefined! ERROR: modpost: "set_mm_exe_file" [test-shadow-newpid.ko] undefined! Examining the /root/.kpatch/patch/ directory reveals, these symbols are never referenced in any relas. readelf -Ws output.o | grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file' 27: 0000000000000000 0 SECTION LOCAL DEFAULT 36 .rodata.release_task.str1.2 45: 0000000000000000 0 SECTION LOCAL DEFAULT 55 .rodata.set_mm_exe_file.str1.2 47: 0000000000000000 0 SECTION LOCAL DEFAULT 57 .rodata.replace_mm_exe_file.str1.2 234: 0000000000000000 0 FUNC GLOBAL DEFAULT UND replace_mm_exe_file 254: 0000000000000000 0 FUNC GLOBAL DEFAULT UND put_task_stack 263: 0000000000000000 0 FUNC GLOBAL DEFAULT UND release_task 269: 0000000000000000 0 FUNC GLOBAL DEFAULT UND set_mm_exe_file readelf -Wr output.o | grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file' Hence, exclude these unreferenced symbols to avoid modpost errors. Fix: * Identify all function symbols present in __bug_table and track their symbol indices. * Exclude .rela__bug_table and .rela__mcount_loc, and for all other relocation sections, check whether any of these symbol indices are actually referenced. * If a symbol index is never referenced in any relevant relocation section and the symbol’s section is not included in the patch, exclude the symbol from being added. Signed-off-by: Sumanth Korikkar --- kpatch-build/create-diff-object.c | 76 +++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 56ade7ef..77581fb1 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -80,7 +80,8 @@ struct special_section { char *name; enum architecture arch; int (*group_size)(struct kpatch_elf *kelf, int offset); - bool (*group_filter)(struct lookup_table *lookup, + bool (*group_filter)(struct kpatch_elf *kelf, + struct lookup_table *lookup, struct section *relasec, unsigned int offset, unsigned int size); }; @@ -2462,7 +2463,72 @@ static int fixup_group_size(struct kpatch_elf *kelf, int offset) return (int)(rela->addend - offset); } -static bool jump_table_group_filter(struct lookup_table *lookup, +/* + * Exclude function symbols absent from any rela sections (except + * .rela__bug_table) to eliminate undefined symbols modpost errors. + */ +static bool bug_table_group_filter(struct kpatch_elf *kelf, + struct lookup_table *lookup, + struct section *relasec, + unsigned int group_offset, + unsigned int group_size) +{ + unsigned int i = 0, count = 0; + unsigned int *symindex; + struct section *sec; + struct symbol *sym; + struct rela *rela; + bool found; + + list_for_each_entry(rela, &relasec->relas, list) { + if (rela->sym->type == STT_FUNC && rela->sym->sec && + !rela->sym->sec->include) + count++; + } + symindex = (unsigned int *)malloc(sizeof(unsigned int) * count); + if (!symindex) + ERROR("malloc"); + list_for_each_entry(rela, &relasec->relas, list) { + if (rela->sym->type == STT_FUNC && rela->sym->sec && + !rela->sym->sec->include) + symindex[i++] = rela->sym->index; + } + for (i = 0; i < count; i++) { + found = false; + list_for_each_entry(sec, &kelf->sections, list) { + if (!is_rela_section(sec) || + is_debug_section(sec)) + continue; + if (!strcmp(sec->name, relasec->name) || + !strcmp(sec->name, ".rela__mcount_loc") || + !sec->include) + continue; + list_for_each_entry(rela, &sec->relas, list) { + if (symindex[i] == rela->sym->index) { + found = true; + break; + } + } + } + if (!found) { + /* + * Function symbol is present in only __bug_table. + * i.e. function symbol was included earlier, but its + * associated section is not included and not + * referenced in any relas. Exclude the function symbol + * to eliminate UND symbols modpost errors. + */ + sym = find_symbol_by_index(&kelf->symbols, symindex[i]); + if (!sym) + ERROR("could not find function symbol\n"); + sym->include = 0; + } + } + return true; +} + +static bool jump_table_group_filter(struct kpatch_elf *kelf, + struct lookup_table *lookup, struct section *relasec, unsigned int group_offset, unsigned int group_size) @@ -2563,7 +2629,8 @@ static bool jump_table_group_filter(struct lookup_table *lookup, return true; } -static bool static_call_sites_group_filter(struct lookup_table *lookup, +static bool static_call_sites_group_filter(struct kpatch_elf *kelf, + struct lookup_table *lookup, struct section *relasec, unsigned int group_offset, unsigned int group_size) @@ -2630,6 +2697,7 @@ static struct special_section special_sections[] = { .name = "__bug_table", .arch = AARCH64 | X86_64 | PPC64 | S390 | LOONGARCH64, .group_size = bug_table_group_size, + .group_filter = bug_table_group_filter, }, { .name = ".fixup", @@ -2837,7 +2905,7 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf, continue; if (special->group_filter && - !special->group_filter(lookup, relasec, src_offset, group_size)) + !special->group_filter(kelf, lookup, relasec, src_offset, group_size)) continue; /*