Live Patching
 help / color / mirror / Atom feed
From: Joe Lawrence <joe.lawrence@redhat.com>
To: live-patching@vger.kernel.org
Cc: Jiri Kosina <jikos@kernel.org>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Miroslav Benes <mbenes@suse.cz>, Petr Mladek <pmladek@suse.com>,
	Song Liu <song@kernel.org>
Subject: [PATCH 1/4] objtool/klp: use patched module name for klp-relocation section naming
Date: Mon, 20 Jul 2026 10:56:55 -0400	[thread overview]
Message-ID: <20260720145658.1103243-2-joe.lawrence@redhat.com> (raw)
In-Reply-To: <20260720145658.1103243-1-joe.lawrence@redhat.com>

Documentation/livepatch/module-elf-format.rst states (and the kernel
currently implements) that the name of a livepatch relocation section
must conform to the following format:

    .klp.rela.objname.section_name

where "objname" determines when the kernel applies the relocations in
this section (i.e., when the "objname" module loads).  This allows
relocations not only for currently loaded kernel objects (like vmlinux
and loaded device drivers), but also for lazy resolution to facilitate
late-module livepatching (for modules loaded after the livepatch).

Previously, objtool's KLP post-link step derived the "objname" from the
klp symbol name, which encoded where the symbol *lives* rather than
which module is being *patched*.  This broke cross-module references
(e.g., can_isotp.ko calling can_rx_unregister() from can.ko),
incorrectly placing them in the .klp.rela.can..text section instead of
.klp.rela.can_isotp..text.

Fix this by adding an 'obj_name' field to the intermediate 'klp_reloc'
struct.  klp-diff populates this field using find_modname(), and
klp-post-link reads it directly to generate the .klp.rela section name.
As a result, each relocation correctly carries its own target module,
regardless of where the referenced symbol originates.

Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
 tools/objtool/include/objtool/klp.h |  1 +
 tools/objtool/klp-diff.c            | 66 +++++++++++++++++++++++------
 tools/objtool/klp-post-link.c       | 20 +++++----
 3 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/tools/objtool/include/objtool/klp.h b/tools/objtool/include/objtool/klp.h
index 6f60cf05db86..bf655b2a7590 100644
--- a/tools/objtool/include/objtool/klp.h
+++ b/tools/objtool/include/objtool/klp.h
@@ -26,6 +26,7 @@
 struct klp_reloc {
 	void *offset;
 	void *sym;
+	void *obj_name;
 	u32 type;
 };
 
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 819f6f167e8c..c5cc54ee562e 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1518,13 +1518,15 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc,
 {
 	struct symbol *patched_sym = patched_reloc->sym;
 	s64 addend = reloc_addend(patched_reloc);
-	const char *sym_modname, *sym_orig_name;
-	static struct section *klp_relocs;
+	const char *sym_modname, *sym_orig_name, *patched_modname;
+	static struct section *klp_relocs, *klp_strs;
+	static struct symbol *klp_strs_sym;
 	struct symbol *sym, *klp_sym;
 	unsigned long klp_reloc_off;
 	char sym_name[SYM_NAME_LEN];
 	struct klp_reloc klp_reloc;
 	unsigned long sympos;
+	s64 str_addend;
 
 	if (!patched_sym->twin) {
 		ERROR("unexpected klp reloc for new symbol %s", patched_sym->name);
@@ -1603,6 +1605,24 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc,
 						0, SHT_PROGBITS, 8, SHF_ALLOC);
 		if (!klp_relocs)
 			return -1;
+
+		klp_strs = find_section_by_name(e->out, KLP_STRINGS_SEC);
+		if (!klp_strs) {
+			klp_strs = elf_create_section(e->out, KLP_STRINGS_SEC,
+						      0, 0, SHT_PROGBITS, 1,
+						      SHF_ALLOC | SHF_STRINGS | SHF_MERGE);
+			if (!klp_strs)
+				return -1;
+			if (elf_add_string(e->out, klp_strs, "") == -1)
+				return -1;
+		}
+
+		klp_strs_sym = klp_strs->sym;
+		if (!klp_strs_sym) {
+			klp_strs_sym = elf_create_section_symbol(e->out, klp_strs);
+			if (!klp_strs_sym)
+				return -1;
+		}
 	}
 
 	klp_reloc_off = sec_size(klp_relocs);
@@ -1627,6 +1647,20 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc,
 			      klp_sym, addend, R_ABS64))
 		return -1;
 
+	/* klp_reloc.obj_name: the patched module, for .klp.rela section naming */
+	patched_modname = find_modname(e);
+	if (!patched_modname)
+		return -1;
+
+	str_addend = elf_add_string(e->out, klp_strs, patched_modname);
+	if (str_addend == -1)
+		return -1;
+
+	if (!elf_create_reloc(e->out, klp_relocs,
+			      klp_reloc_off + offsetof(struct klp_reloc, obj_name),
+			      klp_strs_sym, str_addend, R_ABS64))
+		return -1;
+
 	return 0;
 }
 
@@ -2177,18 +2211,24 @@ static int create_klp_sections(struct elfs *e)
 	if (!funcs_sym)
 		return -1;
 
-	str_sec = elf_create_section(e->out, KLP_STRINGS_SEC, 0, 0,
-				     SHT_PROGBITS, 1,
-				     SHF_ALLOC | SHF_STRINGS | SHF_MERGE);
-	if (!str_sec)
-		return -1;
-
-	if (elf_add_string(e->out, str_sec, "") == -1)
-		return -1;
+	/* clone_reloc_klp() may have already created this section */
+	str_sec = find_section_by_name(e->out, KLP_STRINGS_SEC);
+	if (!str_sec) {
+		str_sec = elf_create_section(e->out, KLP_STRINGS_SEC, 0, 0,
+					     SHT_PROGBITS, 1,
+					     SHF_ALLOC | SHF_STRINGS | SHF_MERGE);
+		if (!str_sec)
+			return -1;
+		if (elf_add_string(e->out, str_sec, "") == -1)
+			return -1;
+	}
 
-	str_sym = elf_create_section_symbol(e->out, str_sec);
-	if (!str_sym)
-		return -1;
+	str_sym = str_sec->sym;
+	if (!str_sym) {
+		str_sym = elf_create_section_symbol(e->out, str_sec);
+		if (!str_sym)
+			return -1;
+	}
 
 	/* allocate klp_object_ext */
 	obj_data = elf_add_data(e->out, obj_sec, NULL, obj_size, true);
diff --git a/tools/objtool/klp-post-link.c b/tools/objtool/klp-post-link.c
index c013e39957b1..141b0a46ca52 100644
--- a/tools/objtool/klp-post-link.c
+++ b/tools/objtool/klp-post-link.c
@@ -39,7 +39,7 @@ static int fix_klp_relocs(struct elf *elf)
 		struct section *sec, *tmp, *klp_rsec;
 		unsigned long offset;
 		struct reloc *reloc;
-		char sym_modname[64];
+		const char *sec_objname;
 		char rsec_name[SEC_NAME_LEN];
 		u64 addend;
 		struct symbol *sym, *klp_sym;
@@ -73,18 +73,20 @@ static int fix_klp_relocs(struct elf *elf)
 		klp_sym = reloc->sym;
 		addend = reloc_addend(reloc);
 
-		/* symbol format: .klp.sym.modname.sym_name,sympos */
-		if (sscanf(klp_sym->name + strlen(KLP_SYM_PREFIX), "%55[^.]", sym_modname) != 1)
-			ERROR("can't find modname in klp symbol '%s'", klp_sym->name);
-
-		/*
-		 * Create the KLP rela:
-		 */
+		/* klp_reloc.obj_name: the patched module name */
+		reloc = find_reloc_by_dest(elf, klp_relocs,
+					   klp_reloc_off + offsetof(struct klp_reloc, obj_name));
+		if (!reloc) {
+			ERROR("malformed " KLP_RELOCS_SEC " section");
+			return -1;
+		}
+		sec_objname = (const char *)reloc->sym->sec->data->d_buf +
+			      reloc_addend(reloc);
 
 		/* section format: .klp.rela.sec_objname.section_name */
 		if (snprintf_check(rsec_name, SEC_NAME_LEN,
 				   KLP_RELOC_SEC_PREFIX "%s.%s",
-				   sym_modname, sec->name))
+				   sec_objname, sec->name))
 			return -1;
 
 		klp_rsec = find_section_by_name(elf, rsec_name);
-- 
2.54.0


  reply	other threads:[~2026-07-20 14:57 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 14:56 [PATCH 0/4] klp-build: klp-relocation fixups Joe Lawrence
2026-07-20 14:56 ` Joe Lawrence [this message]
2026-07-20 14:56 ` [PATCH 2/4] objtool/klp: allow new references to module exports Joe Lawrence
2026-07-20 14:56 ` [PATCH 3/4] objtool/klp: reject new cross-module references without existing dependency Joe Lawrence
2026-07-20 14:56 ` [PATCH 4/4] objtool/klp: strip klp-induced module dependencies from livepatch modules Joe Lawrence

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260720145658.1103243-2-joe.lawrence@redhat.com \
    --to=joe.lawrence@redhat.com \
    --cc=jikos@kernel.org \
    --cc=jpoimboe@kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=pmladek@suse.com \
    --cc=song@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox