Skip to contentSkip to conversation

objtool/klp: Special section validation fixes

PATCH Applied Josh Poimboeuf 3 participants 8 messages Feb 10 – Mar 9

Subsystems (2)
lore
Share & tools
lore

Josh Poimboeuf

author maintainer
#0 lore raw

cover objtool/klp: Special section validation fixes

Fix some issues in validate_special_section_klp_reloc().

Josh Poimboeuf (3):
objtool/klp: Fix detection of corrupt static branch/call entries objtool/klp: Disable unsupported pr_debug() usage objtool/klp: Avoid NULL pointer dereference when printing code symbol
name

 tools/objtool/klp-diff.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)
Signature · 1 line
2.53.0
author maintainer
#1 lore raw

PATCH 1/3 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")
---
 tools/objtool/klp-diff.c | 3 +++
 1 file changed, 3 insertions(+)
tools/objtool/klp-diff.c +3 -0
index 9f1f4011eb9c..d94632e80955 100644
@@ -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) {
 
Signature · 1 line
2.53.0
merge bot Applied
#2 lore raw

[tip: objtool/urgent] objtool/klp: Fix detection of corrupt static branch/call entries

The following commit has been merged into the objtool/urgent branch of tip:

The following commit has been merged into the objtool/urgent branch of tip:

Commit-ID:     f9fb44b0ecefc1f218db56661ed66d4e8d67317d
Gitweb:        https://git.kernel.org/tip/f9fb44b0ecefc1f218db56661ed66d4e8d67317d
Author:        Josh Poimboeuf <[email protected]>
AuthorDate:    Tue, 10 Feb 2026 13:50:09 -08:00
Committer:     Josh Poimboeuf <[email protected]>
CommitterDate: Fri, 06 Mar 2026 07:47:10 -08:00

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")
Reviewed-and-tested-by Song Liu <[email protected]>
---
 tools/objtool/klp-diff.c | 3 +++
 1 file changed, 3 insertions(+)
tools/objtool/klp-diff.c +3 -0
index 9f1f401..d94632e 100644
@@ -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) {
 
author maintainer
#3 lore raw

PATCH 2/3 objtool/klp: Disable unsupported pr_debug() usage

In reply to Josh Poimboeuf

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.

---
 tools/objtool/klp-diff.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)
tools/objtool/klp-diff.c +15 -8
index d94632e80955..9ff65b01882b 100644
@@ -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;
Signature · 1 line
2.53.0
merge bot Applied
#4 lore raw

[tip: objtool/urgent] objtool/klp: Disable unsupported pr_debug() usage

The following commit has been merged into the objtool/urgent branch of tip:

The following commit has been merged into the objtool/urgent branch of tip:

Commit-ID:     e476bb277cf91b7ac3ea803ec78a4f0791bddec3
Gitweb:        https://git.kernel.org/tip/e476bb277cf91b7ac3ea803ec78a4f0791bddec3
Author:        Josh Poimboeuf <[email protected]>
AuthorDate:    Tue, 10 Feb 2026 13:50:10 -08:00
Committer:     Josh Poimboeuf <[email protected]>
CommitterDate: Fri, 06 Mar 2026 07:47:11 -08:00

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.

---
 tools/objtool/klp-diff.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)
tools/objtool/klp-diff.c +15 -8
index d94632e..9ff65b0 100644
@@ -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;
author maintainer
#5 lore raw

PATCH 3/3 objtool/klp: Avoid NULL pointer dereference when printing code symbol name

In reply to Josh Poimboeuf

Fix a hypothetical NULL pointer defereference of the 'code_sym' variable. In theory this should never happen.

---
 tools/objtool/klp-diff.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
tools/objtool/klp-diff.c +9 -6
index 9ff65b01882b..a3198a63c2f0 100644
@@ -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 = "<unknown>";
+
 		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;
 	}
 
Signature · 1 line
2.53.0
merge bot Applied
#6 lore raw

[tip: objtool/urgent] objtool/klp: Avoid NULL pointer dereference when printing code symbol name

The following commit has been merged into the objtool/urgent branch of tip:

The following commit has been merged into the objtool/urgent branch of tip:

Commit-ID:     11c2adcd1fa2a9380a507db1e57c8542bfc81827
Gitweb:        https://git.kernel.org/tip/11c2adcd1fa2a9380a507db1e57c8542bfc81827
Author:        Josh Poimboeuf <[email protected]>
AuthorDate:    Tue, 10 Feb 2026 13:50:11 -08:00
Committer:     Josh Poimboeuf <[email protected]>
CommitterDate: Fri, 06 Mar 2026 07:47:11 -08:00

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.

---
 tools/objtool/klp-diff.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
tools/objtool/klp-diff.c +9 -6
index 9ff65b0..a3198a6 100644
@@ -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 = "<unknown>";
+
 		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;
 	}
 
maintainer
#7 lore raw
In reply to Josh Poimboeuf
Quoted 8 lines · Josh Poimboeuf

Fix some issues in validate_special_section_klp_reloc().

Josh Poimboeuf (3):
objtool/klp: Fix detection of corrupt static branch/call entries objtool/klp: Disable unsupported pr_debug() usage objtool/klp: Avoid NULL pointer dereference when printing code symbol
name

For the set

Reviewed-and-tested-by Song Liu <[email protected]>
Quoted 7 lines
 tools/objtool/klp-diff.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)

--
2.53.0