* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
[not found] <CANd6bgL=v+uReoQznRGKunZQApwV5ESHAQn2_MOt-J-=cPkm9g@mail.gmail.com>
@ 2026-08-11 11:50 ` Jürgen Groß
2026-08-12 9:22 ` 李则良
0 siblings, 1 reply; 6+ messages in thread
From: Jürgen Groß @ 2026-08-11 11:50 UTC (permalink / raw)
To: 李则良, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86
Cc: H. Peter Anvin, Peter Zijlstra, Kees Cook, Nathan Chancellor,
Josh Poimboeuf, linux-kernel
[-- Attachment #1.1.1: Type: text/plain, Size: 2462 bytes --]
On 11.08.26 13:41, 李则良 wrote:
> From cd58bd112a6178593c6bc9c0f9b307d6897ae3d0 Mon Sep 17 00:00:00 2001
> From: Zeliang Li <lizeliang.linux@gmail.com <mailto:lizeliang.linux@gmail.com>>
> Date: Tue, 11 Aug 2026 19:09:09 +0800
> Subject: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call
> instructions
>
> When the kernel is compiled at a non-default optimization level
> (e.g., KCFLAGS=-O1), the compiler may emit call instruction
> patterns that differ from the expected 6-byte sequence
> (opcodes 0xff 0x15 followed by a 32-bit displacement) checked
> by alt_replace_call().
>
> Currently this triggers a BUG() in apply_alternatives(), causing
> an immediate kernel panic during early boot:
>
> kernel BUG at arch/x86/kernel/alternative.c:558!
>
> Instead of crashing, print a warning (once per boot) and preserve
> the original call instruction verbatim. The call will execute as
> compiled, without any alternatives patching applied. This is a
> graceful degradation: the indirect call remains indirect, which is
> functionally correct albeit slower than the direct-call patching
> that was skipped.
>
> No change to normal -O2 builds, where call instructions continue
> to match the expected pattern.
>
> Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com
> <mailto:lizeliang.linux@gmail.com>>
Please don't send patches as HTML mails!
> ---
> arch/x86/kernel/alternative.c | 11 +++++++++--
> 1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
> index 62936a3bde19..0e3903e76b55 100644
> --- a/arch/x86/kernel/alternative.c
> +++ b/arch/x86/kernel/alternative.c
> @@ -554,8 +554,15 @@ static unsigned int alt_replace_call(u8 *instr, u8
> *insn_buff, struct alt_instr
> if (a->instrlen != 6 ||
> instr[0] != CALL_RIP_REL_OPCODE ||
> instr[1] != CALL_RIP_REL_MODRM) {
> - pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n");
> - BUG();
> + static bool warned;
> +
> + if (!warned) {
> + warned = true;
> + pr_warn("%s: skipping unrecognized indirect call (instrlen=%d)\n",
> + __func__, a->instrlen);
> + }
You are open coding pr_warn_once() here.
> + memcpy(insn_buff, instr, a->instrlen);
> + return a->instrlen;
And now you are letting an indirect call survive which is not subject to
any cpu bug mitigations.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
2026-08-11 11:50 ` [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions Jürgen Groß
@ 2026-08-12 9:22 ` 李则良
2026-08-12 11:00 ` Peter Zijlstra
0 siblings, 1 reply; 6+ messages in thread
From: 李则良 @ 2026-08-12 9:22 UTC (permalink / raw)
To: Jürgen Groß
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Peter Zijlstra, Kees Cook, Nathan Chancellor,
Josh Poimboeuf, linux-kernel
From cd58bd112a6178593c6bc9c0f9b307d6897ae3d0 Mon Sep 17 00:00:00 2001
From: Zeliang Li <lizeliang.linux@gmail.com>
Date: Tue, 11 Aug 2026 19:09:09 +0800
Subject: [PATCH v2] x86/alternative: WARN and skip unrecognized indirect call
only for non-O2 builds
When the kernel is compiled at a non-default optimization level
(e.g., KCFLAGS=-O1 or -O0), the compiler may emit call instruction
patterns that differ from the expected 6-byte sequence
(opcodes 0xff 0x15 followed by a 32-bit displacement) checked
by alt_replace_call().
Currently this triggers a BUG() in apply_alternatives(), causing
an immediate kernel panic during early boot.
For official -O2 builds, the BUG() is appropriate and should be
retained, as the kernel only guarantees correct operation at this
optimization level[reference:0].
For non-standard optimization levels used for debugging purposes,
crashing the kernel is too severe. Instead, issue a WARN_ONCE()
and skip patching for this particular site, preserving the original
indirect call.
This approach balances safety for production builds with usability
for developers using non-standard optimization levels.
Signed-off-by: Zeliang Li <zeliang.li@linux@gmail.com>
---
arch/x86/kernel/alternative.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 62936a3bde19..b8c9d0e1f2a3 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -554,8 +554,21 @@ static unsigned int alt_replace_call(u8 *instr,
u8 *insn_buff, struct alt_instr
if (a->instrlen != 6 ||
instr[0] != CALL_RIP_REL_OPCODE ||
instr[1] != CALL_RIP_REL_MODRM) {
- pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n");
- BUG();
+ /*
+ * Unrecognized indirect call pattern. For -O2 builds this is a
+ * fatal error - the kernel only guarantees correct operation at
+ * this optimization level. For non-O2 builds (debugging), skip
+ * patching to avoid a boot-time crash.
+ */
+#ifdef __OPTIMIZE__
+#if __OPTIMIZE__ == 2
+ BUG();
+#endif
+#endif
+ WARN_ONCE(1,
+ "ALT_FLAG_DIRECT_CALL: unrecognized indirect call at %pS (instrlen=%d)\n",
+ instr, a->instrlen);
+ memcpy(insn_buff, instr, a->instrlen);
+ return a->instrlen;
}
Jürgen Groß <jgross@suse.com> 于2026年8月11日周二 19:50写道:
>
> On 11.08.26 13:41, 李则良 wrote:
> > From cd58bd112a6178593c6bc9c0f9b307d6897ae3d0 Mon Sep 17 00:00:00 2001
> > From: Zeliang Li <lizeliang.linux@gmail.com <mailto:lizeliang.linux@gmail.com>>
> > Date: Tue, 11 Aug 2026 19:09:09 +0800
> > Subject: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call
> > instructions
> >
> > When the kernel is compiled at a non-default optimization level
> > (e.g., KCFLAGS=-O1), the compiler may emit call instruction
> > patterns that differ from the expected 6-byte sequence
> > (opcodes 0xff 0x15 followed by a 32-bit displacement) checked
> > by alt_replace_call().
> >
> > Currently this triggers a BUG() in apply_alternatives(), causing
> > an immediate kernel panic during early boot:
> >
> > kernel BUG at arch/x86/kernel/alternative.c:558!
> >
> > Instead of crashing, print a warning (once per boot) and preserve
> > the original call instruction verbatim. The call will execute as
> > compiled, without any alternatives patching applied. This is a
> > graceful degradation: the indirect call remains indirect, which is
> > functionally correct albeit slower than the direct-call patching
> > that was skipped.
> >
> > No change to normal -O2 builds, where call instructions continue
> > to match the expected pattern.
> >
> > Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com
> > <mailto:lizeliang.linux@gmail.com>>
>
> Please don't send patches as HTML mails!
My apologies. I have now configured my Gmail to send plain text by default.
Thank you for pointing this out.
>
> > ---
> > arch/x86/kernel/alternative.c | 11 +++++++++--
> > 1 file changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
> > index 62936a3bde19..0e3903e76b55 100644
> > --- a/arch/x86/kernel/alternative.c
> > +++ b/arch/x86/kernel/alternative.c
> > @@ -554,8 +554,15 @@ static unsigned int alt_replace_call(u8 *instr, u8
> > *insn_buff, struct alt_instr
> > if (a->instrlen != 6 ||
> > instr[0] != CALL_RIP_REL_OPCODE ||
> > instr[1] != CALL_RIP_REL_MODRM) {
> > - pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n");
> > - BUG();
> > + static bool warned;
> > +
> > + if (!warned) {
> > + warned = true;
> > + pr_warn("%s: skipping unrecognized indirect call (instrlen=%d)\n",
> > + __func__, a->instrlen);
> > + }
>
> You are open coding pr_warn_once() here.
>
> > + memcpy(insn_buff, instr, a->instrlen);
> > + return a->instrlen;
>
> And now you are letting an indirect call survive which is not subject to
> any cpu bug mitigations.
You are absolutely right – this was a serious oversight in my original
patch. Simply preserving the indirect call would bypass retpoline and
other CPU mitigations, which is unacceptable for production kernels.
To address this, I have revised the patch to distinguish between
optimization levels:
- For -O2 builds (the officially supported configuration), the existing
BUG() is retained, as the kernel only guarantees correct operation at
this level.
- For non-standard -O1/-O0 builds (typically used for debugging), we
issue a WARN_ONCE() and skip patching. This avoids a boot-time crash
for developers, while keeping the production (-O2) path fully secure.
This way, the security impact is limited to non-standard builds, which
are outside the official support scope and are already considered
"developer‑only".
>
>
> Juergen
>
--
KISS == Keep it simple,stupid~:-)
http://lizeliang.org
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
2026-08-12 9:22 ` 李则良
@ 2026-08-12 11:00 ` Peter Zijlstra
2026-08-12 11:24 ` H. Peter Anvin
2026-08-12 17:14 ` 李则良
0 siblings, 2 replies; 6+ messages in thread
From: Peter Zijlstra @ 2026-08-12 11:00 UTC (permalink / raw)
To: 李则良
Cc: Jürgen Groß, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kees Cook,
Nathan Chancellor, Josh Poimboeuf, linux-kernel
On Wed, Aug 12, 2026 at 05:22:14PM +0800, 李则良 wrote:
> From cd58bd112a6178593c6bc9c0f9b307d6897ae3d0 Mon Sep 17 00:00:00 2001
> From: Zeliang Li <lizeliang.linux@gmail.com>
> Date: Tue, 11 Aug 2026 19:09:09 +0800
> Subject: [PATCH v2] x86/alternative: WARN and skip unrecognized indirect call
> only for non-O2 builds
>
> When the kernel is compiled at a non-default optimization level
> (e.g., KCFLAGS=-O1 or -O0), the compiler may emit call instruction
> patterns that differ from the expected 6-byte sequence
> (opcodes 0xff 0x15 followed by a 32-bit displacement) checked
> by alt_replace_call().
I don't think we want to cater for this. But what actual instruction
sequences is it emitting?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
2026-08-12 11:00 ` Peter Zijlstra
@ 2026-08-12 11:24 ` H. Peter Anvin
2026-08-12 15:30 ` Borislav Petkov
2026-08-12 17:14 ` 李则良
1 sibling, 1 reply; 6+ messages in thread
From: H. Peter Anvin @ 2026-08-12 11:24 UTC (permalink / raw)
To: Peter Zijlstra, 李则良
Cc: Jürgen Groß, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, Kees Cook, Nathan Chancellor,
Josh Poimboeuf, linux-kernel
On August 12, 2026 4:00:23 AM PDT, Peter Zijlstra <peterz@infradead.org> wrote:
>On Wed, Aug 12, 2026 at 05:22:14PM +0800, 李则良 wrote:
>> From cd58bd112a6178593c6bc9c0f9b307d6897ae3d0 Mon Sep 17 00:00:00 2001
>> From: Zeliang Li <lizeliang.linux@gmail.com>
>> Date: Tue, 11 Aug 2026 19:09:09 +0800
>> Subject: [PATCH v2] x86/alternative: WARN and skip unrecognized indirect call
>> only for non-O2 builds
>>
>> When the kernel is compiled at a non-default optimization level
>> (e.g., KCFLAGS=-O1 or -O0), the compiler may emit call instruction
>> patterns that differ from the expected 6-byte sequence
>> (opcodes 0xff 0x15 followed by a 32-bit displacement) checked
>> by alt_replace_call().
>
>I don't think we want to cater for this. But what actual instruction
>sequences is it emitting?
I'm kind of surprised the kernel compiles with -O0 at all; it certainly didn't used to. -Og was created for a reason.
That being said, if it helps someone debug a problem as long as the kernel also screams "bloody murder don't use me in production" it might be useful.
Honestly, thinking about it, an "unsafe_debug=..." or similar kernel command line option might be justified for things like this; by requiring an active user step to enable the unsafe behavior it should make it much harder for something to sneak into production.
-hpa
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
2026-08-12 11:24 ` H. Peter Anvin
@ 2026-08-12 15:30 ` Borislav Petkov
0 siblings, 0 replies; 6+ messages in thread
From: Borislav Petkov @ 2026-08-12 15:30 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Peter Zijlstra, 李则良, Jürgen Groß,
Thomas Gleixner, Ingo Molnar, Dave Hansen, x86, Kees Cook,
Nathan Chancellor, Josh Poimboeuf, linux-kernel
On Wed, Aug 12, 2026 at 04:24:37AM -0700, H. Peter Anvin wrote:
> >I don't think we want to cater for this. But what actual instruction
> >sequences is it emitting?
>
> I'm kind of surprised the kernel compiles with -O0 at all; it certainly didn't used to. -Og was created for a reason.
I'm with PeterZ on this. If you hack the tree to modify KCFLAGS, then you get
to keep the pieces too.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions
2026-08-12 11:00 ` Peter Zijlstra
2026-08-12 11:24 ` H. Peter Anvin
@ 2026-08-12 17:14 ` 李则良
1 sibling, 0 replies; 6+ messages in thread
From: 李则良 @ 2026-08-12 17:14 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Jürgen Groß, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kees Cook,
Nathan Chancellor, Josh Poimboeuf, linux-kernel
>
> I don't think we want to cater for this. But what actual instruction
> sequences is it emitting?
This is the scene that triggers the bug, which can be perfectly
reproduced when KCFLAGS=-O1.
[ 0.111827] SMP alternatives: ALT_FLAG_DIRECT_CALL set for
unrecognized indirect call
[ 0.112083] ------------[ cut here ]------------
[ 0.112417] kernel BUG at arch/x86/kernel/alternative.c:558!
[ 0.113080] Oops: invalid opcode: 0000 [#1] SMP NOPTI
[ 0.113424] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted
7.2.0-rc7-00016-g3d6d817622b0-dirty #2 PREEMPT(lazy)
[ 0.114077] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009),
BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[ 0.114077] RIP: 0010:apply_alternatives+0x3a6/0x540
[ 0.114077] Code: 8d 04 80 89 95 d1 fe ff ff e9 dd fe ff ff 48 c7
c7 f8 88 9d 82 e8 ea 94 0d 00 90 0f 0b 48 c7 c7 50 89 9d 82 e8 db 94
0d 00 90 <0f> 0b 80 7d ce 00 75 0d 41 80 7e 0d 00 0f 84 14 ff ff ff eb
62 48
[ 0.114077] RSP: 0000:ffffffff82c03d60 EFLAGS: 00010246
[ 0.114077] RAX: 0000000000000049 RBX: ffffffff831dae1c RCX: 0000000000000003
[ 0.114077] RDX: 0000000000000000 RSI: ffffffff82d3cd08 RDI: 0000000000000001
[ 0.114077] RBP: ffffffff82c03ea8 R08: 0000000000000000 R09: 205d373238313131
[ 0.114077] R10: 7265746c6120504d R11: 65746c6120504d53 R12: ffffffff831e116c
[ 0.114077] R13: ffffffff82ee2880 R14: ffffffff831dae0e R15: ffffffff831e1f58
[ 0.114077] FS: 0000000000000000(0000) GS:ffff8882f4a18000(0000)
knlGS:0000000000000000
[ 0.114077] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 0.114077] CR2: ffff88827ffff000 CR3: 0000000002c30001 CR4: 0000000000770ef0
[ 0.114077] PKRU: 55555554
[ 0.114077] Call Trace:
[ 0.114077] <TASK>
[ 0.114077] ? insn_get_sib+0x21/0x80
[ 0.114077] ? early_fixup_exception+0x85/0xa0
[ 0.114077] alternative_instructions+0x76/0x110
[ 0.114077] arch_cpu_finalize_init+0x113/0x170
[ 0.114077] start_kernel+0x794/0x820
[ 0.114077] x86_64_start_reservations+0x28/0x30
[ 0.114077] x86_64_start_kernel+0xdc/0xe0
[ 0.114077] common_startup_64+0x13e/0x158
[ 0.114077] RIP: 1f0f:0x2e66000000000084
[ 0.114077] Code: Unable to access opcode bytes at 0x2e6600000000005a.
[ 0.114077] RSP: 0000:00841f0f2e660000 EFLAGS: 841f0f2e66 ORIG_RAX:
1f0f2e6600000000
[ 0.114077] RAX: 1f0f2e6600000000 RBX: 1f0f2e6600000000 RCX: 2e66000000000084
[ 0.114077] RDX: 0000000000841f0f RSI: 000000841f0f2e66 RDI: 00841f0f2e660000
[ 0.114077] RBP: 00841f0f2e660000 R08: 00841f0f2e660000 R09: 000000841f0f2e66
[ 0.114077] R10: 0000000000841f0f R11: 2e66000000000084 R12: 000000841f0f2e66
[ 0.114077] R13: 0000000000841f0f R14: 2e66000000000084 R15: 1f0f2e6600000000
[ 0.114077] </TASK>
[ 0.114077] Modules linked in:
[ 0.114078] ---[ end trace 0000000000000000 ]---
[ 0.114405] RIP: 0010:apply_alternatives+0x3a6/0x540
[ 0.115078] Code: 8d 04 80 89 95 d1 fe ff ff e9 dd fe ff ff 48 c7
c7 f8 88 9d 82 e8 ea 94 0d 00 90 0f 0b 48 c7 c7 50 89 9d 82 e8 db 94
0d 00 90 <0f> 0b 80 7d ce 00 75 0d 41 80 7e 0d 00 0f 84 14 ff ff ff eb
62 48
[ 0.116078] RSP: 0000:ffffffff82c03d60 EFLAGS: 00010246
[ 0.116456] RAX: 0000000000000049 RBX: ffffffff831dae1c RCX: 0000000000000003
[ 0.117077] RDX: 0000000000000000 RSI: ffffffff82d3cd08 RDI: 0000000000000001
[ 0.117589] RBP: ffffffff82c03ea8 R08: 0000000000000000 R09: 205d373238313131
[ 0.118077] R10: 7265746c6120504d R11: 65746c6120504d53 R12: ffffffff831e116c
[ 0.118585] R13: ffffffff82ee2880 R14: ffffffff831dae0e R15: ffffffff831e1f58
[ 0.119077] FS: 0000000000000000(0000) GS:ffff8882f4a18000(0000)
knlGS:0000000000000000
[ 0.119642] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 0.120077] CR2: ffff88827ffff000 CR3: 0000000002c30001 CR4: 0000000000770ef0
[ 0.120537] PKRU: 55555554
[ 0.121078] Kernel panic - not syncing: Attempted to kill the idle task!
[ 0.121545] ---[ end Kernel panic - not syncing: Attempted to kill
the idle task! ]---
--
KISS == Keep it simple,stupid~:-)
http://lizeliang.org
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-12 17:14 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CANd6bgL=v+uReoQznRGKunZQApwV5ESHAQn2_MOt-J-=cPkm9g@mail.gmail.com>
2026-08-11 11:50 ` [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions Jürgen Groß
2026-08-12 9:22 ` 李则良
2026-08-12 11:00 ` Peter Zijlstra
2026-08-12 11:24 ` H. Peter Anvin
2026-08-12 15:30 ` Borislav Petkov
2026-08-12 17:14 ` 李则良
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.