All of lore.kernel.org
 help / color / mirror / Atom feed
* 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.