From f9fb44b0ecefc1f218db56661ed66d4e8d67317d Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 10 Feb 2026 13:50:09 -0800 Subject: objtool/klp: Fix detection of corrupt static branch/call entries Patching a function which references a static key living in a kernel module is unsupported due to ordering issues inherent to late module patching: 1) Load a livepatch module which has a __jump_table entry which needs a klp reloc to reference static key K which lives in module M. 2) The __jump_table klp reloc does *not* get resolved because module M is not yet loaded. 3) jump_label_add_module() corrupts memory (or causes a panic) when dereferencing the uninitialized pointer to key K. validate_special_section_klp_reloc() intends to prevent that from ever happening by catching it at build time. However, it incorrectly assumes the special section entry's reloc symbol references have already been converted from section symbols to object symbols, causing the validation to miss corruption in extracted static branch/call table entries. Make sure the references have been properly converted before doing the validation. Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files") Reported-by: Song Liu Reviewed-and-tested-by: Song Liu Link: https://patch.msgid.link/124ad747b751df0df1725eff89de8332e3fb26d6.1770759954.git.jpoimboe@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 9f1f4011eb9c..d94632e80955 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -1364,6 +1364,9 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym const char *sym_modname; struct export *export; + if (convert_reloc_sym(e->patched, reloc)) + continue; + /* Static branch/call keys are always STT_OBJECT */ if (reloc->sym->type != STT_OBJECT) { -- cgit v1.2.3 From e476bb277cf91b7ac3ea803ec78a4f0791bddec3 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 10 Feb 2026 13:50:10 -0800 Subject: objtool/klp: Disable unsupported pr_debug() usage Instead of erroring out on unsupported pr_debug() (e.g., when patching a module), issue a warning and make it inert, similar to how unsupported tracepoints are currently handled. Reviewed-and-tested-by: Song Liu Link: https://patch.msgid.link/3a7db3a5b7d4abf9b2534803a74e2e7231322738.1770759954.git.jpoimboe@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index d94632e80955..9ff65b01882b 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -1334,18 +1334,18 @@ static bool should_keep_special_sym(struct elf *elf, struct symbol *sym) * be applied after static branch/call init, resulting in code corruption. * * Validate a special section entry to avoid that. Note that an inert - * tracepoint is harmless enough, in that case just skip the entry and print a - * warning. Otherwise, return an error. + * tracepoint or pr_debug() is harmless enough, in that case just skip the + * entry and print a warning. Otherwise, return an error. * - * This is only a temporary limitation which will be fixed when livepatch adds - * support for submodules: fully self-contained modules which are embedded in - * the top-level livepatch module's data and which can be loaded on demand when - * their corresponding to-be-patched module gets loaded. Then klp relocs can - * be retired. + * TODO: This is only a temporary limitation which will be fixed when livepatch + * adds support for submodules: fully self-contained modules which are embedded + * in the top-level livepatch module's data and which can be loaded on demand + * when their corresponding to-be-patched module gets loaded. Then klp relocs + * can be retired. * * Return: * -1: error: validation failed - * 1: warning: tracepoint skipped + * 1: warning: disabled tracepoint or pr_debug() * 0: success */ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym) @@ -1403,6 +1403,13 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym continue; } + if (strstr(reloc->sym->name, "__UNIQUE_ID_ddebug_")) { + WARN("%s: disabling unsupported pr_debug()", + code_sym->name); + ret = 1; + continue; + } + ERROR("%s+0x%lx: unsupported static branch key %s. Use static_key_enabled() instead", code_sym->name, code_offset, reloc->sym->name); return -1; -- cgit v1.2.3 From 11c2adcd1fa2a9380a507db1e57c8542bfc81827 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 10 Feb 2026 13:50:11 -0800 Subject: objtool/klp: Avoid NULL pointer dereference when printing code symbol name Fix a hypothetical NULL pointer defereference of the 'code_sym' variable. In theory this should never happen. Reviewed-and-tested-by: Song Liu Link: https://patch.msgid.link/64116517bc93851a98fe366ea0a4d807f4c70aab.1770759954.git.jpoimboe@kernel.org Signed-off-by: Josh Poimboeuf --- tools/objtool/klp-diff.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tools/objtool/klp-diff.c') diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 9ff65b01882b..a3198a63c2f0 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -1352,7 +1352,7 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym { bool static_branch = !strcmp(sym->sec->name, "__jump_table"); bool static_call = !strcmp(sym->sec->name, ".static_call_sites"); - struct symbol *code_sym = NULL; + const char *code_sym = NULL; unsigned long code_offset = 0; struct reloc *reloc; int ret = 0; @@ -1372,7 +1372,7 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym /* Save code location which can be printed below */ if (reloc->sym->type == STT_FUNC && !code_sym) { - code_sym = reloc->sym; + code_sym = reloc->sym->name; code_offset = reloc_addend(reloc); } @@ -1395,23 +1395,26 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym if (!strcmp(sym_modname, "vmlinux")) continue; + if (!code_sym) + code_sym = ""; + if (static_branch) { if (strstarts(reloc->sym->name, "__tracepoint_")) { WARN("%s: disabling unsupported tracepoint %s", - code_sym->name, reloc->sym->name + 13); + code_sym, reloc->sym->name + 13); ret = 1; continue; } if (strstr(reloc->sym->name, "__UNIQUE_ID_ddebug_")) { WARN("%s: disabling unsupported pr_debug()", - code_sym->name); + code_sym); ret = 1; continue; } ERROR("%s+0x%lx: unsupported static branch key %s. Use static_key_enabled() instead", - code_sym->name, code_offset, reloc->sym->name); + code_sym, code_offset, reloc->sym->name); return -1; } @@ -1422,7 +1425,7 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym } ERROR("%s()+0x%lx: unsupported static call key %s. Use KLP_STATIC_CALL() instead", - code_sym->name, code_offset, reloc->sym->name); + code_sym, code_offset, reloc->sym->name); return -1; } -- cgit v1.2.3