lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <176060833150.709179.6653461924795727998.tip-bot2@tip-bot2>
Date: Thu, 16 Oct 2025 09:52:11 -0000
From: "tip-bot2 for Josh Poimboeuf" <tip-bot2@...utronix.de>
To: linux-tip-commits@...r.kernel.org
Cc: Petr Mladek <pmladek@...e.com>, Joe Lawrence <joe.lawrence@...hat.com>,
 Josh Poimboeuf <jpoimboe@...nel.org>, x86@...nel.org,
 linux-kernel@...r.kernel.org
Subject:
 [tip: objtool/core] objtool: Add base objtool support for livepatch modules

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

Commit-ID:     164c9201e1dad8d5c0c38f583dba81e4b6da9cc7
Gitweb:        https://git.kernel.org/tip/164c9201e1dad8d5c0c38f583dba81e4b6da9cc7
Author:        Josh Poimboeuf <jpoimboe@...nel.org>
AuthorDate:    Wed, 17 Sep 2025 09:04:03 -07:00
Committer:     Josh Poimboeuf <jpoimboe@...nel.org>
CommitterDate: Tue, 14 Oct 2025 14:50:18 -07:00

objtool: Add base objtool support for livepatch modules

In preparation for klp-build, enable "classic" objtool to work on
livepatch modules:

  - Avoid duplicate symbol/section warnings for prefix symbols and the
    .static_call_sites and __mcount_loc sections which may have already
    been extracted by klp diff.

  - Add __klp_funcs to the IBT function pointer section whitelist.

  - Prevent KLP symbols from getting incorrectly classified as cold
    subfunctions.

Acked-by: Petr Mladek <pmladek@...e.com>
Tested-by: Joe Lawrence <joe.lawrence@...hat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@...nel.org>
---
 tools/objtool/check.c                   | 52 +++++++++++++++++++++---
 tools/objtool/elf.c                     |  5 +-
 tools/objtool/include/objtool/elf.h     |  1 +-
 tools/objtool/include/objtool/objtool.h |  2 +-
 4 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index b2659fb..d071fbf 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@...hat.com>
  */
 
+#define _GNU_SOURCE /* memmem() */
 #include <string.h>
 #include <stdlib.h>
 #include <inttypes.h>
@@ -611,6 +612,20 @@ static int init_pv_ops(struct objtool_file *file)
 	return 0;
 }
 
+static bool is_livepatch_module(struct objtool_file *file)
+{
+	struct section *sec;
+
+	if (!opts.module)
+		return false;
+
+	sec = find_section_by_name(file->elf, ".modinfo");
+	if (!sec)
+		return false;
+
+	return memmem(sec->data->d_buf, sec_size(sec), "\0livepatch=Y", 12);
+}
+
 static int create_static_call_sections(struct objtool_file *file)
 {
 	struct static_call_site *site;
@@ -622,7 +637,14 @@ static int create_static_call_sections(struct objtool_file *file)
 
 	sec = find_section_by_name(file->elf, ".static_call_sites");
 	if (sec) {
-		WARN("file already has .static_call_sites section, skipping");
+		/*
+		 * Livepatch modules may have already extracted the static call
+		 * site entries to take advantage of vmlinux static call
+		 * privileges.
+		 */
+		if (!file->klp)
+			WARN("file already has .static_call_sites section, skipping");
+
 		return 0;
 	}
 
@@ -666,7 +688,7 @@ static int create_static_call_sections(struct objtool_file *file)
 
 		key_sym = find_symbol_by_name(file->elf, tmp);
 		if (!key_sym) {
-			if (!opts.module) {
+			if (!opts.module || file->klp) {
 				ERROR("static_call: can't find static_call_key symbol: %s", tmp);
 				return -1;
 			}
@@ -885,7 +907,13 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 
 	sec = find_section_by_name(file->elf, "__mcount_loc");
 	if (sec) {
-		WARN("file already has __mcount_loc section, skipping");
+		/*
+		 * Livepatch modules have already extracted their __mcount_loc
+		 * entries to cover the !CONFIG_FTRACE_MCOUNT_USE_OBJTOOL case.
+		 */
+		if (!file->klp)
+			WARN("file already has __mcount_loc section, skipping");
+
 		return 0;
 	}
 
@@ -2569,6 +2597,8 @@ static bool validate_branch_enabled(void)
 
 static int decode_sections(struct objtool_file *file)
 {
+	file->klp = is_livepatch_module(file);
+
 	mark_rodata(file);
 
 	if (init_pv_ops(file))
@@ -4244,6 +4274,9 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
  *   - compiler cloned functions (*.cold, *.part0, etc)
  *   - asm functions created with inline asm or without SYM_FUNC_START()
  *
+ * Also, the function may already have a prefix from a previous objtool run
+ * (livepatch extracted functions, or manually running objtool multiple times).
+ *
  * So return 0 if the NOPs are missing or the function already has a prefix
  * symbol.
  */
@@ -4266,6 +4299,14 @@ static int create_prefix_symbol(struct objtool_file *file, struct symbol *func)
 	if (snprintf_check(name, SYM_NAME_LEN, "__pfx_%s", func->name))
 		return -1;
 
+	if (file->klp) {
+		struct symbol *pfx;
+
+		pfx = find_symbol_by_offset(func->sec, func->offset - opts.prefix);
+		if (pfx && is_prefix_func(pfx) && !strcmp(pfx->name, name))
+			return 0;
+	}
+
 	insn = find_insn(file, func->sec, func->offset);
 	if (!insn) {
 		WARN("%s: can't find starting instruction", func->name);
@@ -4618,6 +4659,7 @@ static int validate_ibt(struct objtool_file *file)
 		    !strncmp(sec->name, ".debug", 6)			||
 		    !strcmp(sec->name, ".altinstructions")		||
 		    !strcmp(sec->name, ".ibt_endbr_seal")		||
+		    !strcmp(sec->name, ".kcfi_traps")			||
 		    !strcmp(sec->name, ".orc_unwind_ip")		||
 		    !strcmp(sec->name, ".retpoline_sites")		||
 		    !strcmp(sec->name, ".smp_locks")			||
@@ -4627,12 +4669,12 @@ static int validate_ibt(struct objtool_file *file)
 		    !strcmp(sec->name, "__bug_table")			||
 		    !strcmp(sec->name, "__ex_table")			||
 		    !strcmp(sec->name, "__jump_table")			||
+		    !strcmp(sec->name, "__klp_funcs")			||
 		    !strcmp(sec->name, "__mcount_loc")			||
-		    !strcmp(sec->name, ".kcfi_traps")			||
 		    !strcmp(sec->name, ".llvm.call-graph-profile")	||
 		    !strcmp(sec->name, ".llvm_bb_addr_map")		||
 		    !strcmp(sec->name, "__tracepoints")			||
-		    strstr(sec->name, "__patchable_function_entries"))
+		    !strcmp(sec->name, "__patchable_function_entries"))
 			continue;
 
 		for_each_reloc(sec->rsec, reloc)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4bb7ce9..5feeefc 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -499,7 +499,10 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
 	     strstarts(sym->name, "__pi___cfi_")))
 		sym->prefix = 1;
 
-	if (is_func_sym(sym) && strstr(sym->name, ".cold"))
+	if (strstarts(sym->name, ".klp.sym"))
+		sym->klp = 1;
+
+	if (!sym->klp && is_func_sym(sym) && strstr(sym->name, ".cold"))
 		sym->cold = 1;
 	sym->pfunc = sym->cfunc = sym;
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 60f844e..21d8b82 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -88,6 +88,7 @@ struct symbol {
 	u8 debug_checksum    : 1;
 	u8 changed	     : 1;
 	u8 included	     : 1;
+	u8 klp		     : 1;
 	struct list_head pv_target;
 	struct reloc *relocs;
 	struct section *group_sec;
diff --git a/tools/objtool/include/objtool/objtool.h b/tools/objtool/include/objtool/objtool.h
index 7f70b41..f7051bb 100644
--- a/tools/objtool/include/objtool/objtool.h
+++ b/tools/objtool/include/objtool/objtool.h
@@ -28,7 +28,7 @@ struct objtool_file {
 	struct list_head mcount_loc_list;
 	struct list_head endbr_list;
 	struct list_head call_list;
-	bool ignore_unreachables, hints, rodata;
+	bool ignore_unreachables, hints, rodata, klp;
 
 	unsigned int nr_endbr;
 	unsigned int nr_endbr_int;

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ