Live Patching
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Longjun Luo" <luolongjuna@gmail.com>,
	jpoimboe@kernel.org, peterz@infradead.org
Cc: mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
	song@kernel.org, puranjay@kernel.org, nathan@kernel.org,
	ndesaulniers@google.com, morbo@google.com,
	justinstitt@google.com, live-patching@vger.kernel.org
Subject: Re: [RFC PATCH v2 08/11] objtool/klp: Include symbol identities in reference checksums
Date: Wed, 04 Nov 2026 14:06:07 +0000	[thread overview]
Message-ID: <sashiko-outbox-197391@kernel.org> (raw)
In-Reply-To: <20261104133158.3187525-9-luolongjuna@gmail.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Medium] objtool/klp: incomplete .lto_priv suffix handling in checksum_name()
- [Medium] objtool/klp: alias checksum mismatch in checksum_object() and klp-diff
- [Medium] objtool/klp: broken .rodata and cross-CU matching in fallback_by_name()
- [Medium] objtool/klp: missing alias and TU checks in check_linkage_changes()
--

commit 4c8f17799f11215eb7f986c3b3afec4af75ec543
Author: Longjun Luo <luolongjuna@gmail.com>

objtool/klp: Include symbol identities in reference checksums

This commit updates livepatch checksum calculation to prepare DWARF
identities and hash symbol identity paths for named references instead of
relying solely on suffix-stripped ELF names.

> diff --git a/tools/objtool/klp-checksum.c b/tools/objtool/klp-checksum.c
> index 1a5f2fa89baa5..44c0eb784e570 100644
> --- a/tools/objtool/klp-checksum.c
> +++ b/tools/objtool/klp-checksum.c
> @@ -77,6 +77,12 @@ static bool is_const_reference(struct symbol *sym)
>  static int checksum_object(struct objtool_file *file, struct symbol *sym,
>  			   unsigned int depth);
>  
> +/* Use suffix-stripped ELF names for references without DWARF identities. */
> +static const char *checksum_name(struct symbol *sym)
> +{
> +	return sym->identity.path ?: sym->identity.demangled_name;
> +}

[Severity: Medium]
When building with GCC LTO, GCC appends .lto_priv.<num> suffixes to
privatized symbols. In tools/objtool/klp-diff.c, same_compiler_name() calls
skip_lto_priv() so that symbols whose .lto_priv.<num> suffix is added or
removed between original and patched builds can still correlate:

tools/objtool/klp-diff.c:skip_lto_priv() {
	if (!strstarts(name, ".lto_priv.") || !isdigit((unsigned char)name[10]))
		return name;
	name += 10;
	while (isdigit((unsigned char)*name))
		name++;
	return name;
}

However, demangled_name_len() in tools/objtool/elf.c only strips .llvm.<hash>
and trailing .<digits> suffixes:

tools/objtool/elf.c:demangled_name_len() {
	...
	while (len && isdigit(name[len - 1])) {
		p = name + len - 1;
		while (p > name && isdigit(*p))
			p--;

		if (p == name || *p != '.')
			break;
		len = p - name;
	}
	return len;
}

As a result, a symbol like foo.lto_priv.0 has sym->identity.demangled_name
truncated to foo.lto_priv instead of foo, which also leaves .lto_priv in
sym->identity.path. In addition, matches_name() in tools/objtool/klp-dwarf.c
only skips .llvm. and .<digits>, rejecting .lto_priv.<num> when matching ELF
names against DWARF DW_AT_name, and find_twin() in tools/objtool/klp-diff.c
keys hash lookups and same_identity() on sym->identity.demangled_name before
calling is_twin_candidate() -> compatible_symbol_name() ->
same_compiler_name() -> skip_lto_priv().

If a referenced symbol gains or loses a .lto_priv.<num> suffix between
builds, won't checksum_name() hash different strings and cause false checksum
mismatches as well as failed symbol correlation?

> @@ -170,8 +176,8 @@ static int checksum_update_insn(struct objtool_file *file, struct symbol *func,
>  		__checksum_update_insn(func, insn, &sym->csum.checksum,
>  				       sizeof(sym->csum.checksum));
>  	} else {
> -		__checksum_update_insn(func, insn, sym->identity.demangled_name,
> -				       strlen(sym->identity.demangled_name));
> +		__checksum_update_insn(func, insn, checksum_name(sym),
> +				       strlen(checksum_name(sym)));
>  	}
>  	__checksum_update_insn(func, insn, &offset, sizeof(offset));

[Severity: Medium]
In calculate_checksums(), symbols where is_alias_sym(sym) is true are skipped
so that only the representative symbol sym->alias gets a checksum in
.discard.sym_checksum.

However, in checksum_update_insn() and checksum_update_object(), compound
constants are hashed by calling checksum_object() directly on sym without
resolving sym->alias or checking whether the checksum was already computed:

tools/objtool/klp-checksum.c:checksum_update_insn() {
	...
	if (is_compound_constant(sym)) {
		if (checksum_object(file, sym, 1))
			return -1;
		__checksum_update_insn(func, insn, &sym->csum.checksum,
				       sizeof(sym->csum.checksum));
	}
}

And on the diff side in tools/objtool/klp-diff.c, read_sym_checksums() only
populates csum.checksum on sym->alias (leaving sym->csum.checksum == 0 on
aliases), whereas correlate_by_identity() pairs aliased static objects
directly via orig_sym->twin = patched_sym, and mark_changed_functions() and
find_twin_by_identity_and_checksum() inspect sym->csum.checksum directly
rather than sym->alias->csum.checksum:

tools/objtool/klp-diff.c:mark_changed_functions() {
	...
		if (orig_sym->csum.checksum != patched_sym->csum.checksum) {
			if (!is_func_sym(orig_sym)) {
				ERROR("changed data: %s", orig_sym->name);
				return -1;
			}
}

Doesn't this emit duplicate .discard.sym_checksum entries for compound
constant aliases, and cause mark_changed_functions() to falsely report
changed data when constant merging or symbol table ordering changes which
symbol is the representative alias?

> @@ -411,6 +418,12 @@ int cmd_klp_checksum(int argc, const char **argv)
>  	if (ret)
>  		goto out;
>  
> +	for_each_sym(file->elf, sym)
> +		sym->dont_correlate = dont_correlate(sym);
> +	ret = prepare_identities(file->elf);
> +	if (ret)
> +		goto out;
> +
>  	ret = calculate_checksums(file);
>  	if (ret)
>  		goto out;

[Severity: Medium]
Now that cmd_klp_checksum() calls prepare_identities(),
get_identity_for_symbol() invokes fallback_by_name() in
tools/objtool/klp-dwarf.c when no matching address DIE is found:

tools/objtool/klp-dwarf.c:fallback_by_name() {
	const char *name = sym->pfunc->identity.demangled_name;
	const char *file = sym->file ? basename(sym->file->name) : NULL;
	...
	elf_hash_for_each_possible(elf, dwarf_name, entry, name_hash, str_hash(name)) {
		if (entry->type != sym->type || strcmp(name, entry->name))
			continue;
		...
		if (!entry->cu->assembly && !candidate.external && file &&
		    strcmp(file, basename(candidate.source)) &&
		    !known_file_name_mismatch(file, basename(candidate.source)))
			continue;
}

Could this fail in two cases for .rodata symbols?

First, under Clang, function-local static const objects in .rodata have ELF
names of the form <func>.<var>[.<suffix>], so
sym->pfunc->identity.demangled_name is <func>.<var>, whereas dwarf_name is
indexed by DW_AT_name (<var>), so strcmp(name, entry->name) never matches.

Second, for top-level .rodata symbols in multi-TU objects where two CUs share
the same basename, fallback_by_name() does not exclude DIEs that already have
concrete addresses (entry->nr_addresses > 0), skips the file check when
candidate.external is true, and only compares basename(sym->file->name)
against basename(candidate.source) rather than checking
sym->file->identity.source. Can a .rodata symbol without a location attribute
in one CU match a same-named DIE in another CU and cause
complete_file_source() to fail with conflicting DWARF sources?

[Severity: Medium]
Also related to identity handling in tools/objtool/klp-diff.c,
check_linkage_changes() checks orig_sym->twin and patched_sym->twin directly
when scanning for linkage changes across symbols with the same demangled
name:

tools/objtool/klp-diff.c:check_linkage_changes() {
	for_each_sym(e->orig, orig_sym) {
		if (orig_sym->twin || orig_sym->dont_correlate ||
		    !has_dwarf_identity(orig_sym) || is_undef_sym(orig_sym) || !orig_sym->len)
			continue;

		for_each_sym_by_demangled_name(e->patched, orig_sym->identity.demangled_name,
					       patched_sym) {
			if (patched_sym->twin || patched_sym->dont_correlate ||
			    !has_dwarf_identity(patched_sym) ||
			    is_undef_sym(patched_sym) || !patched_sym->len)
				continue;

			if (orig_sym->type != patched_sym->type ||
			    strcmp(orig_sym->identity.scope, patched_sym->identity.scope) ||
			    orig_sym->identity.external == patched_sym->identity.external)
				continue;

			ERROR("unsupported linkage change for %s",
			      orig_sym->identity.demangled_name);
			return -1;
		}
	}
}

Unlike correlate_symbols() and validate_symbol_twins(), which use
reference_twin(sym) so data aliases whose representative symbol is correlated
are treated as correlated, check_linkage_changes() checks sym->twin directly
and does not check whether orig_sym and patched_sym belong to the same
translation unit.

In a multi-TU object or an object with correlated data aliases, won't an
uncorrelated static symbol in one TU matching the demangled name of an
uncorrelated global symbol in a different TU (or an uncorrelated alias of a
correlated symbol) trigger a false "unsupported linkage change" error?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261104133158.3187525-1-luolongjuna@gmail.com?part=8

  reply	other threads:[~2026-11-04 14:06 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04 13:31 [RFC PATCH v2 00/11] objtool/klp: DWARF-based cross-build symbol correlation Longjun Luo
2026-11-04 13:31 ` [RFC PATCH v2 01/11] objtool/klp: Fix checksums and copying of wide strings Longjun Luo
2026-11-04 14:03   ` sashiko-bot
2026-11-04 13:31 ` [RFC PATCH v2 02/11] objtool/klp: Hash compound literals by content Longjun Luo
2026-11-04 13:55   ` sashiko-bot
2026-11-04 13:31 ` [RFC PATCH v2 03/11] objtool/klp: Preserve identifier digits when stripping suffixes Longjun Luo
2026-11-04 13:31 ` [RFC PATCH v2 04/11] objtool/klp: Read symbol identities from DWARF Longjun Luo
2026-11-04 13:51   ` sashiko-bot
2026-11-04 13:31 ` [RFC PATCH v2 05/11] objtool/klp: Support reduced and split DWARF Longjun Luo
2026-11-04 13:31 ` [RFC PATCH v2 06/11] klp-build: Require CONFIG_DEBUG_INFO Longjun Luo
2026-11-04 13:31 ` [RFC PATCH v2 07/11] objtool/klp: Correlate symbols using DWARF identities Longjun Luo
2026-11-04 14:09   ` sashiko-bot
2026-11-04 13:31 ` [RFC PATCH v2 08/11] objtool/klp: Include symbol identities in reference checksums Longjun Luo
2026-11-04 14:06   ` sashiko-bot [this message]
2026-11-04 13:31 ` [RFC PATCH v2 09/11] objtool/klp: Extend twins through unchanged function references Longjun Luo
2026-11-04 14:05   ` sashiko-bot
2026-11-04 13:31 ` [RFC PATCH v2 10/11] objtool/klp: Check unmatched data references Longjun Luo
2026-11-04 13:31 ` [RFC PATCH v2 11/11] objtool/klp: Test symbol identity and state preservation Longjun Luo
2026-11-04 13:50   ` sashiko-bot

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=sashiko-outbox-197391@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=justinstitt@google.com \
    --cc=live-patching@vger.kernel.org \
    --cc=luolongjuna@gmail.com \
    --cc=mbenes@suse.cz \
    --cc=morbo@google.com \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=peterz@infradead.org \
    --cc=pmladek@suse.com \
    --cc=puranjay@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --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