From nobody Thu Sep 24 20:03:25 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 401AD47206E; Mon, 21 Sep 2026 09:27:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789982862; cv=none; b=Q3AUHFodbOFtsOALLJYrs+Kdkit334oAqR5xupFEv9E78ZIbqE0P3CCcjAQXAcuO6Jc7FQRmjxaKcWoVLJMMrd+JQTL5dbekFvHGThBju7BMxjOP3aNDVBA0YyfNyN3bPE+TwAh7X6xdpxJcLj+ySNhjCoPO77MGZmUDR22GCxw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789982862; c=relaxed/simple; bh=4NdZJ3G05DAJZvBPPvckl+xbDuYQzb6LJLnP7puXjiU=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=RWst33Qp2p4/6kjsYfWxt2zz18DoIn2bg6vAx2X3BHG0zbwVWpMFdqtIPoW8b6VjZZxDA02cOVRR2uUV2WfbICPzg7tbAMEe1mlNFJXqZmPWV3Q7t2VIoG/8uPuffz+E7c218nkI+czv0hJEK4zbEE0QYX9RbfDr16z8BuqzeV0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=nxq2nYGo; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=LGxQ/AXM; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="nxq2nYGo"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="LGxQ/AXM" Date: Mon, 21 Sep 2026 09:27:36 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1789982858; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=X8iqzuJfGjpMekwqxkcvnS6x/Q8gK/dCyxM0oySOBtA=; b=nxq2nYGocybrVYMr5uabXcfNkhy/7QrfTmiziTfGbJNWPxYVfPn//I2N9czgmgtks2kn6f BHxi9GO4uIixbHqIqF5YIBs5MAytmH0HYQm7er20qB6RHJQdeEpj1XXE/+pax0RXjmpEZY GabGW5kWk1t7k2IkQXEU4XL0LLXRUT7Tbqvx+oSbkYvh3pVKXEIJYNFTf10lKPHPQrpkRD FAoG/PnommwAkvxiiZqCP3+AFhxp3XBCAz8tEbtEVPUJK50eIOAiXpjgn6xahn8sGUMmjd 7VmBx+wSoU0lIDfgriyd0mv14ET0k83S539PlcY745o1sKtpN7oq4zavJrDzQQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1789982858; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=X8iqzuJfGjpMekwqxkcvnS6x/Q8gK/dCyxM0oySOBtA=; b=LGxQ/AXMoJjPfbmc7nYN3MdMJddvDdmlN+JlZGXboEtCFcvIPlpmYVd3i9w7aVfX6F5ANz bRykXoOqyht8mvBw== From: "tip-bot2 for Song Liu" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: objtool/core] objtool/klp: Add test for alternative replacement code in checksums Cc: Song Liu , Josh Poimboeuf , Ingo Molnar , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260916184351.2720310-53-song@kernel.org> References: <20260916184351.2720310-53-song@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <178998285653.2819794.16898813643107121985.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the objtool/core branch of tip: Commit-ID: 32b2cf11305d6c355e66b7f9fb827d7e97c2a5c3 Gitweb: https://git.kernel.org/tip/32b2cf11305d6c355e66b7f9fb827d7e9= 7c2a5c3 Author: Song Liu AuthorDate: Wed, 16 Sep 2026 11:43:45 -07:00 Committer: Ingo Molnar CommitterDate: Mon, 21 Sep 2026 11:12:07 +02:00 objtool/klp: Add test for alternative replacement code in checksums checksum_update_insn() walks insn->alts after hashing the instruction itself: the alternative's type, and where the replacement forms a group, its feature number and every instruction in it. A patch which edits only the replacement -- code that runs on some CPUs and not others -- still has to move the function's checksum. When it does not, klp diff calls the function unchanged and leaves it out. The patch ships the old replacement, and the bug is fixed only on machines whose CPU takes the other arm. Which machines those are depends on the feature bit, so it presents as a machine-specific bug rather than a missing patch. insn->alts is built by objtool's check pass, not by the compiler, so the pair goes through that first. --mcount is the action used: it is the cheapest one that does not also need --link. Two of the three paths are isolated. Skipping the alts walk and dropping the feature hash both make this fail, and the second of those only exists inside the alt_group branch, so reaching it proves the grouped path is taken. The alternative's type is hashed but not varied here -- the fixture emits one kind of alternative -- so that line is covered without being isolated, as is the in_alt recursion guard, which wants nested alternatives. Assisted-by: Claude:claude-opus-4 Based-on-test-by: Joe Lawrence Assisted-by: Claude:claude-opus-5 Signed-off-by: Song Liu Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Link: https://patch.msgid.link/20260916184351.2720310-53-song@kernel.org --- tools/objtool/tests/x86/fixtures/checksum_alt.c | 66 ++++++++++++++++- tools/objtool/tests/x86/test-checksum-alt.sh | 45 +++++++++++- 2 files changed, 111 insertions(+) create mode 100644 tools/objtool/tests/x86/fixtures/checksum_alt.c create mode 100755 tools/objtool/tests/x86/test-checksum-alt.sh diff --git a/tools/objtool/tests/x86/fixtures/checksum_alt.c b/tools/objtoo= l/tests/x86/fixtures/checksum_alt.c new file mode 100644 index 0000000..ed342d9 --- /dev/null +++ b/tools/objtool/tests/x86/fixtures/checksum_alt.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * An x86 alternative whose replacement code is part of the patched functi= on's + * checksum. + * + * checksum_update_insn() walks insn->alts after hashing the instruction + * itself, hashing the alternative's type and, when the replacement forms a + * group, its feature number and every instruction in it. So editing only= the + * replacement -- code the CPU may or may not ever run -- has to move the + * function's checksum. + * + * It is reached through objtool's own alternative handling, so the object= has + * to go through the check pass first: insn->alts is built there, not by t= he + * compiler. + * + * struct alt_instr is written out by hand as in empty_alternative.c: s32 + * instr_offset, s32 repl_offset, u32 ft_flags, u8 instrlen, u8 replacemen= tlen. + * + * Variants, applied to the patched build only: + * + * ALT_REPL the replacement instruction changes; the original does n= ot + * ALT_FEATURE the feature number changes; no code changes at all + */ + +static const char __modinfo[] + __attribute__((section(".modinfo"), used, aligned(1))) =3D "\0name=3Dvmli= nux"; + +/* + * Both spellings are two bytes, because a replacement may not be longer t= han + * the instruction it replaces: "xchg %ax, %ax" is 66 90 and two nops are + * 90 90. The original below is padded to match. + */ +#if defined(PATCHED) && defined(ALT_REPL) +#define REPL_INSN " nop\n\t nop\n\t" +#else +#define REPL_INSN " xchg %ax, %ax\n\t" +#endif + +#if defined(PATCHED) && defined(ALT_FEATURE) +#define FEATURE "7" +#else +#define FEATURE "3" +#endif + +int target(int x) +{ + asm volatile( + "661: nop\n\t" + " nop\n\t" + "662:\n\t" + ".pushsection .altinstr_replacement, \"ax\"\n\t" + ".globl target_repl\n\t" + "target_repl:\n\t" + REPL_INSN + "target_repl_end:\n\t" + ".popsection\n\t" + ".pushsection .altinstructions, \"aM\", @progbits, 14\n\t" + ".long 661b - .\n\t" + ".long target_repl - .\n\t" + ".long " FEATURE "\n\t" + ".byte 662b - 661b\n\t" + ".byte target_repl_end - target_repl\n\t" + ".popsection\n\t"); + + return x + 1; +} diff --git a/tools/objtool/tests/x86/test-checksum-alt.sh b/tools/objtool/t= ests/x86/test-checksum-alt.sh new file mode 100755 index 0000000..74ebfca --- /dev/null +++ b/tools/objtool/tests/x86/test-checksum-alt.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# An alternative's replacement code counts towards the checksum of the fun= ction +# it belongs to. +# +# checksum_update_insn() walks insn->alts after hashing the instruction it= self: +# the alternative's type, and where the replacement forms a group, its fea= ture +# number and every instruction in it. So a patch which edits only the +# replacement -- code that runs on some CPUs and not others -- still has to +# move the function's checksum. +# +# If it does not, klp diff decides the function is unchanged and leaves it= out. +# The patch then ships the old replacement, and the bug is fixed only on +# machines whose CPU takes the other arm. Which machines those are depend= s on +# the feature bit, so the failure looks like a machine-specific bug rather= than +# a missing patch. +# +# insn->alts exists only after objtool's check pass, so the pair goes thro= ugh +# that first -- the compiler emits none of this structure itself. +# +# Covers the same ground as corpus/x86_64/checksum-alt-group, +# checksum-alt-no-group and checksum-alt-recursion-guard in Joe Lawrence's +# klp-build unit test corpus. + +. "$(dirname "$0")/../lib.sh" + +setup + +check() +{ + build_pair checksum_alt.c "-D$1" + assert_input_section .altinstructions + run_objtool_check --mcount + run_checksum + + assert_checksum_differs target +} + +# The replacement instruction itself. +check ALT_REPL +# The feature number, with no instruction anywhere changed. +check ALT_FEATURE + +pass "alternative replacement code counts towards the checksum"