From: Song Liu <song@kernel.org>
To: live-patching@vger.kernel.org
Cc: jpoimboe@kernel.org, peterz@infradead.org, jikos@kernel.org,
mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
puranjay@kernel.org, kernel-team@meta.com,
Song Liu <song@kernel.org>
Subject: [PATCH 46/58] objtool/klp: Add test for data object checksums
Date: Fri, 11 Sep 2026 11:50:19 -0700 [thread overview]
Message-ID: <20260911185031.1534046-21-song@kernel.org> (raw)
In-Reply-To: <20260911185031.1534046-1-song@kernel.org>
klp checksum hashes a data symbol's length, its bytes, and every relocation
it carries -- as the target's name and adjusted addend, except a reference
into a string section, which contributes the string's contents instead.
Nothing covered any of it.
Each is load-bearing, and the failure is always the same shape: a checksum
which ignores one calls a changed object unchanged, klp diff leaves it out
of the patch, and the patched code goes on reading the kernel's old copy.
The string case cannot be caught by hashing bytes: the pointer is
identical, same section and same offset, and only the text it refers to
moved.
One fixture, six variants applied to the patched build alone. Each was
verified by sabotaging the line it covers and watching the test fail:
raw bytes initialiser change
length a .bss object grows; its bytes are never hashed
string contents literal edited in place, pointer untouched
reloc target name pointer moved to another function
reloc addend same array, different index
section-symbol path the same, via a static's section symbol
Two of those needed the fixture rebuilding. An initialised array does not
isolate the length, because growing one changes the hashed bytes too --
hence .bss, where there are none. And a named char[] does not reach the
contents-hashing path at all: that keys on SHF_STRINGS, which the compiler
sets on the mergeable section a literal lands in and not on an array given
a section of its own.
Assisted-by: Claude:claude-opus-4
Based-on-test-by: Joe Lawrence <joe.lawrence@redhat.com>
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@kernel.org>
---
.../tests/generic/fixtures/checksum_data.c | 116 ++++++++++++++++++
.../tests/generic/test-checksum-data.sh | 61 +++++++++
2 files changed, 177 insertions(+)
create mode 100644 tools/objtool/tests/generic/fixtures/checksum_data.c
create mode 100755 tools/objtool/tests/generic/test-checksum-data.sh
diff --git a/tools/objtool/tests/generic/fixtures/checksum_data.c b/tools/objtool/tests/generic/fixtures/checksum_data.c
new file mode 100644
index 000000000000..6310af5c02d3
--- /dev/null
+++ b/tools/objtool/tests/generic/fixtures/checksum_data.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Data objects whose checksums must move for reasons the raw bytes do not
+ * show.
+ *
+ * checksum_update_object() hashes a data symbol's length and its bytes, and
+ * then walks its relocations: a reference into a string section contributes
+ * the string's *contents*, and any other reference contributes the target
+ * symbol's name and the adjusted addend. So three changes that leave the
+ * object's own bytes identical still have to change its checksum:
+ *
+ * Each variant is selected by a -D on the patched build only, so the original
+ * is always the baseline:
+ *
+ * WHICH_FUNC the function pointer points somewhere else
+ * WHICH_STR the string pointer points at a different literal
+ * STR_CONTENT the string it points at is edited in place
+ * WHICH_SLOT the same array, at a different index: addend only
+ * WHICH_PRIV likewise, but a static, reached through its section symbol
+ *
+ * The last is the interesting one. Nothing in the pointer changes -- same
+ * section, same offset -- so a checksum that hashed only the relocation and
+ * not what it referred to would call the object unchanged, and the patched
+ * kernel would keep the old string.
+ */
+
+static const char __modinfo[]
+ __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
+
+int callee_a(int x);
+int callee_b(int x);
+int callee_a(int x) { return x + 1; }
+int callee_b(int x) { return x + 2; }
+
+/*
+ * String *literals*, not named arrays. The contents-hashing path keys on
+ * SHF_STRINGS, which the compiler sets on the mergeable .rodata.str1.1 a
+ * literal lands in and not on a named char[] given a section of its own. A
+ * fixture using the latter exercises the ordinary name-and-addend path and
+ * reports nothing when the text changes.
+ */
+#if defined(PATCHED) && defined(STR_CONTENT)
+#define MESSAGE "edited"
+#else
+#define MESSAGE "original"
+#endif
+
+/* A plain data object: only its own bytes decide the checksum. */
+#if defined(PATCHED) && defined(PLAIN_VALUE)
+int plain = 43;
+#else
+int plain = 42;
+#endif
+
+/*
+ * A .bss object, where length is the only thing there is to hash: the section
+ * has no data, so the bytes are skipped and only sym->len distinguishes this
+ * from an object of another size. An initialised array would not isolate it
+ * -- growing one changes the hashed bytes as well.
+ */
+#if defined(PATCHED) && defined(LONGER)
+char sized[4];
+#else
+char sized[2];
+#endif
+
+/*
+ * A reference into the middle of an array: same target symbol, different
+ * addend. Nothing else in the object changes, so this is the only way to see
+ * whether the addend is hashed at all.
+ */
+int slots[4];
+
+/*
+ * A file-local array. A reference to a static lands on its section symbol
+ * plus an offset, so the hash has to resolve that back to the underlying
+ * object before it has a name to hash at all -- a different code path from the
+ * global above, and one that silently contributes nothing when it fails.
+ */
+static int priv_slots[4];
+
+struct desc {
+ int (*fn)(int arg);
+ const char *str;
+ int *slot;
+ int *priv;
+};
+
+const struct desc descriptor = {
+#if defined(PATCHED) && defined(WHICH_FUNC)
+ .fn = callee_b,
+#else
+ .fn = callee_a,
+#endif
+#if defined(PATCHED) && defined(WHICH_STR)
+ .str = "a different literal",
+#else
+ .str = MESSAGE,
+#endif
+#if defined(PATCHED) && defined(WHICH_SLOT)
+ .slot = &slots[2],
+#else
+ .slot = &slots[1],
+#endif
+#if defined(PATCHED) && defined(WHICH_PRIV)
+ .priv = &priv_slots[3],
+#else
+ .priv = &priv_slots[1],
+#endif
+};
+
+int target(int x)
+{
+ return descriptor.fn(x) + plain + sized[0] + (int)descriptor.str[0] +
+ *descriptor.slot + *descriptor.priv;
+}
diff --git a/tools/objtool/tests/generic/test-checksum-data.sh b/tools/objtool/tests/generic/test-checksum-data.sh
new file mode 100755
index 000000000000..e915026b79a7
--- /dev/null
+++ b/tools/objtool/tests/generic/test-checksum-data.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# What a data object's checksum has to cover.
+#
+# checksum_update_object() hashes the symbol's length, its bytes (when the
+# section has any -- .bss does not), and then
+# every relocation it carries -- as the target's name plus the adjusted addend,
+# except for a reference into a string section, which contributes the string's
+# contents instead.
+#
+# Each of those is load-bearing, and the failure is always the same shape: a
+# checksum that ignores one of them calls a changed object unchanged, klp diff
+# leaves it out of the patch, and the patched code goes on reading the
+# kernel's old copy. Nothing says so at build time.
+#
+# The string case is the one that cannot be caught by hashing bytes alone. The
+# pointer is identical -- same section, same offset -- and only the text it
+# refers to moved.
+#
+# Covers the same ground as corpus/x86_64/checksum-data-basic,
+# checksum-data-func-ptr, checksum-data-string-ptr and checksum-string-reloc in
+# Joe Lawrence's klp-build unit test corpus.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+
+# check <flag> <symbol> <what changed>
+#
+# Build the pair with one difference and require that symbol's checksum to move.
+check()
+{
+ build_pair checksum_data.c "-D$1"
+ run_checksum
+
+ assert_checksum_differs "$2"
+}
+
+# The object's own bytes.
+check PLAIN_VALUE plain
+# Its length, for a .bss object whose bytes are not hashed at all.
+check LONGER sized
+# A relocation's target: same bytes in the object, different symbol named.
+check WHICH_FUNC descriptor
+check WHICH_STR descriptor
+# The contents of a string the object points at, with the pointer untouched.
+check STR_CONTENT descriptor
+# A relocation's addend: same target symbol, different offset into it.
+check WHICH_SLOT descriptor
+# The same, for a static reached through its section symbol: the reference has
+# to be resolved back to the object before there is a name or offset to hash.
+check WHICH_PRIV descriptor
+
+# Having shown five things that must change it, show one that must not: an
+# unrelated edit elsewhere in the file leaves this object alone.
+build_pair checksum_data.c -DPLAIN_VALUE
+run_checksum
+assert_checksum_matches descriptor
+
+pass "data checksums cover length, bytes, reloc targets and string contents"
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-11 18:52 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 18:42 [PATCH 00/58] Unit test framework for klp-build toolchain Song Liu
2026-09-11 18:42 ` [PATCH 01/58] objtool: Add test harness for the klp subcommands Song Liu
2026-09-11 18:42 ` [PATCH 02/58] objtool/klp: Check the klp test environment once, before any test Song Liu
2026-09-11 19:02 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 03/58] objtool/klp: Group the klp tests by architecture Song Liu
2026-09-11 18:42 ` [PATCH 04/58] objtool/klp: Classify klp test outcomes Song Liu
2026-09-11 18:42 ` [PATCH 05/58] objtool/klp: Build klp test fixtures through the harness Song Liu
2026-09-11 18:42 ` [PATCH 06/58] objtool/klp: Grow the klp test harness vocabulary Song Liu
2026-09-11 19:03 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 07/58] objtool/klp: Give each run one working directory, one per test inside it Song Liu
2026-09-11 18:42 ` [PATCH 08/58] objtool/klp: Run the klp tests under set -u Song Liu
2026-09-11 18:42 ` [PATCH 09/58] objtool/klp: Document the klp test harness Song Liu
2026-09-11 19:00 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 10/58] objtool: Keep failing test workdirs by default Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 11/58] objtool: Forward toolchain variables to the klp test runner Song Liu
2026-09-11 18:42 ` [PATCH 12/58] objtool/klp: Add test for rejecting changed data Song Liu
2026-09-11 18:42 ` [PATCH 13/58] objtool/klp: Add test for newly introduced data Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 14/58] objtool/klp: Add test for newly introduced functions Song Liu
2026-09-11 18:42 ` [PATCH 15/58] objtool/klp: Add test for static local correlation Song Liu
2026-09-11 18:42 ` [PATCH 16/58] objtool/klp: Add test for cold function halves Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 17/58] objtool/klp: Add test for special section extraction Song Liu
2026-09-11 18:42 ` [PATCH 18/58] objtool/klp: Add test for selective " Song Liu
2026-09-11 18:42 ` [PATCH 19/58] objtool/klp: Add test for jump table key relocations Song Liu
2026-09-11 18:42 ` [PATCH 20/58] objtool/klp: Add test for rejecting module-owned static branch keys Song Liu
2026-09-11 18:42 ` [PATCH 21/58] objtool/klp: Add test for rejecting module-owned static call keys Song Liu
2026-09-11 18:42 ` [PATCH 22/58] objtool/klp: Add test for symids in discarded sections Song Liu
2026-09-11 18:42 ` [PATCH 23/58] objtool/klp: Add test for rejecting references to init code/data Song Liu
2026-09-11 19:18 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 24/58] objtool/klp: Add test for correlation across ThinLTO name mangling Song Liu
2026-09-11 18:42 ` [PATCH 25/58] objtool/klp: Add test for objects without .modinfo Song Liu
2026-09-11 18:49 ` [PATCH 26/58] objtool/klp: Add test for unchecksummed input Song Liu
2026-09-11 18:50 ` [PATCH 27/58] objtool/klp: Add klp diff and post-link regression tests Song Liu
2026-09-11 18:50 ` [PATCH 28/58] objtool/klp: Add test for klp reloc section naming in module objects Song Liu
2026-09-11 18:50 ` [PATCH 29/58] objtool/klp: Add test for vmlinux relocs in a patched module Song Liu
2026-09-11 18:50 ` [PATCH 30/58] objtool/klp: Add test for Module.symvers path normalization Song Liu
2026-09-11 18:50 ` [PATCH 31/58] objtool/klp: Add test for the contents of the klp_funcs list Song Liu
2026-09-11 18:50 ` [PATCH 32/58] objtool/klp: Add test for EXPORT_SYMBOL_FOR_MODULES references Song Liu
2026-09-11 18:50 ` [PATCH 33/58] objtool/klp: Add test for new references to exported symbols Song Liu
2026-09-11 18:50 ` [PATCH 34/58] objtool/klp: Add test for empty x86 alternative replacements Song Liu
2026-09-11 18:50 ` [PATCH 35/58] objtool/klp: Add test for recorded checksum values Song Liu
2026-09-11 18:50 ` [PATCH 36/58] objtool/klp: Add test for position-independent checksums Song Liu
2026-09-11 19:16 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 37/58] objtool/klp: Add test for sympos in module objects Song Liu
2026-09-11 19:21 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 38/58] objtool/klp: Add test for sympos resolved against a linked vmlinux Song Liu
2026-09-11 18:50 ` [PATCH 39/58] objtool/klp: Add test for static locals which must not be correlated Song Liu
2026-09-11 18:50 ` [PATCH 40/58] objtool/klp: Add test for __bug_table, __ex_table and __mcount_loc extraction Song Liu
2026-09-11 19:20 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 41/58] objtool/klp: Add test for kCFI prefix symbols and traps Song Liu
2026-09-11 19:21 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 42/58] objtool/klp: Add test for symbols whose linkage the patch changes Song Liu
2026-09-11 18:50 ` [PATCH 43/58] objtool/klp: Test rejection of a file-local static branch key Song Liu
2026-09-11 18:50 ` [PATCH 44/58] objtool/klp: Test a hand-built livepatch module's static call keys Song Liu
2026-09-11 18:50 ` [PATCH 45/58] objtool/klp: Test text annotations on alternative replacements Song Liu
2026-09-11 18:50 ` Song Liu [this message]
2026-09-11 18:50 ` [PATCH 47/58] objtool/klp: Add test for symbols with no checksum entry of their own Song Liu
2026-09-11 19:23 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 48/58] objtool/klp: Add test for a static branch introduced by the patch Song Liu
2026-09-11 18:50 ` [PATCH 49/58] objtool/klp: Add test for tracepoint and pr_debug static branch keys Song Liu
2026-09-11 18:50 ` [PATCH 50/58] objtool/klp: Add test for a static call introduced by the patch Song Liu
2026-09-11 19:25 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 51/58] objtool/klp: Add test for instruction operand checksums Song Liu
2026-09-11 18:50 ` [PATCH 52/58] objtool/klp: Add test for alternative replacement code in checksums Song Liu
2026-09-11 19:30 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 53/58] objtool/klp: Add test for the alignment of cloned data sections Song Liu
2026-09-11 18:50 ` [PATCH 54/58] objtool/klp: Add test for a patch which strips a data annotation Song Liu
2026-09-11 19:24 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 55/58] objtool/klp: Add test for absolute and __ADDRESSABLE symbols Song Liu
2026-09-11 18:50 ` [PATCH 56/58] objtool/klp: Add test for UBSAN metadata in an unchanged function Song Liu
2026-09-11 18:50 ` [PATCH 57/58] objtool/klp: Add test for Clang switch jump tables Song Liu
2026-09-11 19:27 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 58/58] objtool/klp: Add test for ThinLTO symbols sharing a demangled name Song Liu
2026-09-11 19:28 ` sashiko-bot
2026-09-13 1:53 ` [PATCH 00/58] Unit test framework for klp-build toolchain Josh Poimboeuf
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=20260911185031.1534046-21-song@kernel.org \
--to=song@kernel.org \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=kernel-team@meta.com \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=puranjay@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.