* 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; 12+ 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] 12+ 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; 12+ 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] 12+ 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; 12+ 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] 12+ 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; 12+ 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] 12+ 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; 12+ 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] 12+ 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 ` 李则良 2026-08-12 19:01 ` H. Peter Anvin ` (2 more replies) 1 sibling, 3 replies; 12+ 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] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-12 17:14 ` 李则良 @ 2026-08-12 19:01 ` H. Peter Anvin 2026-08-12 19:02 ` H. Peter Anvin 2026-08-13 9:51 ` Peter Zijlstra 2 siblings, 0 replies; 12+ messages in thread From: H. Peter Anvin @ 2026-08-12 19:01 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 10:14:41 AM PDT, "李则良" <lizeliang.linux@gmail.com> wrote: >> >> 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! ]--- > Well, what about -Og? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-12 17:14 ` 李则良 2026-08-12 19:01 ` H. Peter Anvin @ 2026-08-12 19:02 ` H. Peter Anvin 2026-08-13 9:51 ` Peter Zijlstra 2 siblings, 0 replies; 12+ messages in thread From: H. Peter Anvin @ 2026-08-12 19:02 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 10:14:41 AM PDT, "李则良" <lizeliang.linux@gmail.com> wrote: >> >> 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! ]--- > That a UD2 opcode... ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-12 17:14 ` 李则良 2026-08-12 19:01 ` H. Peter Anvin 2026-08-12 19:02 ` H. Peter Anvin @ 2026-08-13 9:51 ` Peter Zijlstra 2026-08-13 19:35 ` 李则良 2 siblings, 1 reply; 12+ messages in thread From: Peter Zijlstra @ 2026-08-13 9:51 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 Thu, Aug 13, 2026 at 01:14:41AM +0800, 李则良 wrote: > > > > 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. > That's not what I asked, now was it. I asked what opcodes it does generate. Disassemble an affected function and show the difference between the normal -O2 and your -O1 build that causes the failure. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-13 9:51 ` Peter Zijlstra @ 2026-08-13 19:35 ` 李则良 2026-08-13 19:57 ` 李则良 0 siblings, 1 reply; 12+ messages in thread From: 李则良 @ 2026-08-13 19:35 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 [-- Attachment #1: Type: text/plain, Size: 3290 bytes --] > > That's not what I asked, now was it. I asked what opcodes it does > generate. Disassemble an affected function and show the difference > between the normal -O2 and your -O1 build that causes the failure. on vmlinux-O1: (gdb) until arch/x86/kernel/alternative.c:557 alt_replace_call (instr=0xffffffff82f447e5 <early_fixup_exception+133> "\377S\b\220\220\353\371[A\\]\303\314\314\314\314\303\314\314\314\314f\017\037D", insn_buff=0xffffffff82c03d78 <init_thread_union+15736> "\350\263\177\020\377", a=0xffffffff831dae0e) at arch/x86/kernel/alternative.c:557 557 pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n"); vmlinux-O1: 0xffffffff82f447e5 <+133>: ff 53 08 call QWORD PTR [rbx+0x8] 0xffffffff82f447e8 <+136>: 90 nop 0xffffffff82f447e9 <+137>: 90 nop 0xffffffff82f447ea <+138>: eb f9 jmp 0xffffffff82f447e5 <early_fixup_exception+133> 0xffffffff82f447ec <+140>: 5b pop rbx 0xffffffff82f447ed <+141>: 41 5c pop r12 vmlinux-O2: 0xffffffff82f3bf4b <+123>: 74 b0 je 0xffffffff82f3befd <early_fixup_exception+45> 0xffffffff82f3bf4d <+125>: eb 08 jmp 0xffffffff82f3bf57 <early_fixup_exception+135> 0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR [rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8> 0xffffffff82f3bf55 <+133>: eb f8 jmp 0xffffffff82f3bf4f <early_fixup_exception+127> 0xffffffff82f3bf57 <+135>: 5b pop rbx 0xffffffff82f3bf58 <+136>: 41 5c pop r12 0xffffffff82f3bf5a <+138>: 5d pop rbp I use the patch below to bypass the problem while keeping all logic of alt_replace_call intact. From 2538684697e537298aa9082b582bc7dddd29b278 Mon Sep 17 00:00:00 2001 From: Zeliang Li <lizeliang.linux@gmail.com> Date: Fri, 14 Aug 2026 02:32:19 +0800 Subject: [PATCH] x86/mm: force O2 optimization for early_fixup_exception When the kernel is compiled with non-standard optimization flags (e.g., KCFLAGS=-O1), the function early_fixup_exception may be compiled to an indirect call instruction that is not recognized by alt_replace_call() (e.g., "call *0x8(%rbx)"). This triggers a BUG() during early boot, as seen in: ALT_FLAG_DIRECT_CALL: original instruction is not a 6-byte ... instruction at early_fixup_exception+0x85/0xa0, length=5 instruction bytes: ff 53 08 90 90 Force this function to be compiled with -O2 optimization level, which guarantees the standard 6-byte `ff 15 <disp32>` form used by alternatives patching. Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com> --- arch/x86/mm/extable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index ceb8d03191ab..5d5c7510a817 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -375,6 +375,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, extern unsigned int early_recursion_flag; /* Restricted version used during very early boot */ +__attribute__((optimize("O2"))) void __init early_fixup_exception(struct pt_regs *regs, int trapnr) { /* Ignore early NMIs. */ -- 2.53.0 -- KISS == Keep it simple,stupid~:-) http://lizeliang.org [-- Attachment #2: O2-gdb --] [-- Type: application/octet-stream, Size: 3595 bytes --] (gdb) set disassembly-flavor intel (gdb) disassemble /r early_fixup_exception Dump of assembler code for function early_fixup_exception: 0xffffffff82f3bed0 <+0>: f3 0f 1e fa endbr64 0xffffffff82f3bed4 <+4>: 83 fe 02 cmp esi,0x2 0xffffffff82f3bed7 <+7>: 0f 84 83 00 00 00 je 0xffffffff82f3bf60 <early_fixup_exception+144> 0xffffffff82f3bedd <+13>: 55 push rbp 0xffffffff82f3bede <+14>: 48 89 e5 mov rbp,rsp 0xffffffff82f3bee1 <+17>: 41 54 push r12 0xffffffff82f3bee3 <+19>: 53 push rbx 0xffffffff82f3bee4 <+20>: 83 3d 15 61 0a 00 02 cmp DWORD PTR [rip+0xa6115],0x2 # 0xffffffff82fe2000 <early_recursion_flag> 0xffffffff82f3beeb <+27>: 77 62 ja 0xffffffff82f3bf4f <early_fixup_exception+127> 0xffffffff82f3beed <+29>: 41 89 f4 mov r12d,esi 0xffffffff82f3bef0 <+32>: 48 89 fb mov rbx,rdi 0xffffffff82f3bef3 <+35>: 66 83 bf 88 00 00 00 10 cmp WORD PTR [rdi+0x88],0x10 0xffffffff82f3befb <+43>: 74 2f je 0xffffffff82f3bf2c <early_fixup_exception+92> 0xffffffff82f3befd <+45>: 41 0f 20 d1 mov r9,cr2 0xffffffff82f3bf01 <+49>: 48 8b 8b 80 00 00 00 mov rcx,QWORD PTR [rbx+0x80] 0xffffffff82f3bf08 <+56>: 4c 8b 43 78 mov r8,QWORD PTR [rbx+0x78] 0xffffffff82f3bf0c <+60>: 44 89 e6 mov esi,r12d 0xffffffff82f3bf0f <+63>: 48 c7 c7 2c 5a 83 82 mov rdi,0xffffffff82835a2c 0xffffffff82f3bf16 <+70>: 0f b7 93 88 00 00 00 movzx edx,WORD PTR [rbx+0x88] 0xffffffff82f3bf1d <+77>: e8 ae fa 3c fe call 0xffffffff8130b9d0 <early_printk> 0xffffffff82f3bf22 <+82>: 48 89 df mov rdi,rbx 0xffffffff82f3bf25 <+85>: e8 86 c9 30 fe call 0xffffffff812488b0 <show_regs> 0xffffffff82f3bf2a <+90>: eb 23 jmp 0xffffffff82f3bf4f <early_fixup_exception+127> 0xffffffff82f3bf2c <+92>: 48 8b 57 78 mov rdx,QWORD PTR [rdi+0x78] 0xffffffff82f3bf30 <+96>: 31 c9 xor ecx,ecx 0xffffffff82f3bf32 <+98>: e8 39 c9 34 fe call 0xffffffff81288870 <fixup_exception> 0xffffffff82f3bf37 <+103>: 85 c0 test eax,eax 0xffffffff82f3bf39 <+105>: 75 1c jne 0xffffffff82f3bf57 <early_fixup_exception+135> 0xffffffff82f3bf3b <+107>: 41 83 fc 06 cmp r12d,0x6 0xffffffff82f3bf3f <+111>: 75 bc jne 0xffffffff82f3befd <early_fixup_exception+45> 0xffffffff82f3bf41 <+113>: 48 89 df mov rdi,rbx 0xffffffff82f3bf44 <+116>: e8 97 93 10 ff call 0xffffffff820452e0 <handle_bug> 0xffffffff82f3bf49 <+121>: 84 c0 test al,al 0xffffffff82f3bf4b <+123>: 74 b0 je 0xffffffff82f3befd <early_fixup_exception+45> 0xffffffff82f3bf4d <+125>: eb 08 jmp 0xffffffff82f3bf57 <early_fixup_exception+135> 0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR [rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8> 0xffffffff82f3bf55 <+133>: eb f8 jmp 0xffffffff82f3bf4f <early_fixup_exception+127> 0xffffffff82f3bf57 <+135>: 5b pop rbx 0xffffffff82f3bf58 <+136>: 41 5c pop r12 0xffffffff82f3bf5a <+138>: 5d pop rbp 0xffffffff82f3bf5b <+139>: e9 50 75 11 ff jmp 0xffffffff820534b0 <__x86_return_thunk> 0xffffffff82f3bf60 <+144>: e9 4b 75 11 ff jmp 0xffffffff820534b0 <__x86_return_thunk> End of assembler dump. (gdb) [-- Attachment #3: O1-gdb --] [-- Type: application/octet-stream, Size: 4327 bytes --] (gdb) until arch/x86/kernel/alternative.c:557 alt_replace_call (instr=0xffffffff82f447e5 <early_fixup_exception+133> "\377S\b\220\220\353\371[A\\]\303\314\314\314\314\303\314\314\314\314f\017\037D", insn_buff=0xffffffff82c03d78 <init_thread_union+15736> "\350\263\177\020\377", a=0xffffffff831dae0e) at arch/x86/kernel/alternative.c:557 557 pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n"); (gdb) set disassembly-flavor intel (gdb) disassemble /r early_fixup_exception Dump of assembler code for function early_fixup_exception: 0xffffffff82f44760 <+0>: f3 0f 1e fa endbr64 0xffffffff82f44764 <+4>: 83 fe 02 cmp esi,0x2 0xffffffff82f44767 <+7>: 0f 84 88 00 00 00 je 0xffffffff82f447f5 <early_fixup_exception+149> 0xffffffff82f4476d <+13>: 55 push rbp 0xffffffff82f4476e <+14>: 48 89 e5 mov rbp,rsp 0xffffffff82f44771 <+17>: 41 54 push r12 0xffffffff82f44773 <+19>: 53 push rbx 0xffffffff82f44774 <+20>: 48 89 fb mov rbx,rdi 0xffffffff82f44777 <+23>: 41 89 f4 mov r12d,esi 0xffffffff82f4477a <+26>: 83 3d 7f b8 0a 00 02 cmp DWORD PTR [rip+0xab87f],0x2 # 0xffffffff82ff0000 <early_recursion_flag> 0xffffffff82f44781 <+33>: 77 5b ja 0xffffffff82f447de <early_fixup_exception+126> 0xffffffff82f44783 <+35>: 66 83 bf 88 00 00 00 10 cmp WORD PTR [rdi+0x88],0x10 0xffffffff82f4478b <+43>: 75 24 jne 0xffffffff82f447b1 <early_fixup_exception+81> 0xffffffff82f4478d <+45>: 48 8b 57 78 mov rdx,QWORD PTR [rdi+0x78] 0xffffffff82f44791 <+49>: b9 00 00 00 00 mov ecx,0x0 0xffffffff82f44796 <+54>: e8 35 0d 34 fe call 0xffffffff812854d0 <fixup_exception> 0xffffffff82f4479b <+59>: 85 c0 test eax,eax 0xffffffff82f4479d <+61>: 75 4d jne 0xffffffff82f447ec <early_fixup_exception+140> 0xffffffff82f4479f <+63>: 41 83 fc 06 cmp r12d,0x6 0xffffffff82f447a3 <+67>: 75 0c jne 0xffffffff82f447b1 <early_fixup_exception+81> 0xffffffff82f447a5 <+69>: 48 89 df mov rdi,rbx 0xffffffff82f447a8 <+72>: e8 d3 3d 3a ff call 0xffffffff822e8580 <handle_bug> 0xffffffff82f447ad <+77>: 84 c0 test al,al 0xffffffff82f447af <+79>: 75 3b jne 0xffffffff82f447ec <early_fixup_exception+140> 0xffffffff82f447b1 <+81>: 41 0f 20 d1 mov r9,cr2 0xffffffff82f447b5 <+85>: 48 8b 8b 80 00 00 00 mov rcx,QWORD PTR [rbx+0x80] 0xffffffff82f447bc <+92>: 0f b7 93 88 00 00 00 movzx edx,WORD PTR [rbx+0x88] 0xffffffff82f447c3 <+99>: 4c 8b 43 78 mov r8,QWORD PTR [rbx+0x78] 0xffffffff82f447c7 <+103>: 44 89 e6 mov esi,r12d 0xffffffff82f447ca <+106>: 48 c7 c7 08 32 9e 82 mov rdi,0xffffffff829e3208 0xffffffff82f447d1 <+113>: e8 ba a0 3d fe call 0xffffffff8131e890 <early_printk> 0xffffffff82f447d6 <+118>: 48 89 df mov rdi,rbx 0xffffffff82f447d9 <+121>: e8 82 73 2f fe call 0xffffffff8123bb60 <show_regs> 0xffffffff82f447de <+126>: 48 c7 c3 80 f1 c3 82 mov rbx,0xffffffff82c3f180 0xffffffff82f447e5 <+133>: ff 53 08 call QWORD PTR [rbx+0x8] 0xffffffff82f447e8 <+136>: 90 nop 0xffffffff82f447e9 <+137>: 90 nop 0xffffffff82f447ea <+138>: eb f9 jmp 0xffffffff82f447e5 <early_fixup_exception+133> 0xffffffff82f447ec <+140>: 5b pop rbx 0xffffffff82f447ed <+141>: 41 5c pop r12 0xffffffff82f447ef <+143>: 5d pop rbp 0xffffffff82f447f0 <+144>: c3 ret 0xffffffff82f447f1 <+145>: cc int3 0xffffffff82f447f2 <+146>: cc int3 --Type <RET> for more, q to quit, c to continue without paging-- 0xffffffff82f447f3 <+147>: cc int3 0xffffffff82f447f4 <+148>: cc int3 0xffffffff82f447f5 <+149>: c3 ret 0xffffffff82f447f6 <+150>: cc int3 0xffffffff82f447f7 <+151>: cc int3 0xffffffff82f447f8 <+152>: cc int3 0xffffffff82f447f9 <+153>: cc int3 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-13 19:35 ` 李则良 @ 2026-08-13 19:57 ` 李则良 2026-08-14 10:15 ` Jürgen Groß 0 siblings, 1 reply; 12+ messages in thread From: 李则良 @ 2026-08-13 19:57 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 am currently testing the more general approach shown below. Your review is also appreciated. on vmlinux-O1: 0xffffffff82f447de <+126>: ff 15 a4 a9 cf ff call QWORD PTR [rip+0xffffffffffcfa9a4] # 0xffffffff82c3f188 <pv_ops+8> 0xffffffff82f447e4 <+132>: eb f8 jmp 0xffffffff82f447de <early_fixup_exception+126> 0xffffffff82f447e6 <+134>: 5b pop rbx 0xffffffff82f447e7 <+135>: 41 5c pop r12 0xffffffff82f447e9 <+137>: 5d pop rbp on vmlinux-O2: 0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR [rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8> 0xffffffff82f3bf55 <+133>: eb f8 jmp 0xffffffff82f3bf4f <early_fixup_exception+127> 0xffffffff82f3bf57 <+135>: 5b pop rbx 0xffffffff82f3bf58 <+136>: 41 5c pop r12 0xffffffff82f3bf5a <+138>: 5d pop rbp This is an early draft – please review. Thanks in advance. From 5989dcf448e4d23ea4f3a0f91fec34f3dd25d26c Mon Sep 17 00:00:00 2001 From: Zeliang Li <lizeliang.linux@gmail.com> Date: Fri, 14 Aug 2026 03:17:38 +0800 Subject: [PATCH] x86/paravirt: Force RIP-relative paravirt calls under low optimization levels When compiling the kernel with non-standard lower optimization levels like -O1 (e.g., during specific debugging or framework testing setups) using newer toolchains like GCC 15.2.0, the compiler exhibits passive register hoisting. In complex code paths like early_fixup_exception(), it caches the base address of the global 'pv_ops' structure into a general-purpose register instead of issuing direct RIP-relative memory loads, producing: mov $0xffffffff82c3f180, %rbx call *0x8(%rbx) While this behavior is bypassed under aggressive -O2 optimizations, under -O1 it leaves a register-relative indirect call. This violates the strict format assertion in the x86 alternative text-patching engine (alt_replace_call), which expects an 'ALT_FLAG_DIRECT_CALL' site to be a standard 6-byte RIP-relative indirect call (ff 15), leading to a boot-time kernel BUG. Fix this by changing the x86_64 paravirt inline assembly to use an "i" (immediate) constraint for the function pointer address, and explicitly reference it via (%rip) in the assembly template. This removes the toolchain's ability to select any other addressing mode, guaranteeing the emission of compliant 'call *pv_ops+offset(%rip)' sequences on x86_64 regardless of the active compiler -O flag. For i386, the original "m" constraint is retained since RIP-relative addressing does not exist on 32-bit x86. Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com> --- arch/x86/include/asm/paravirt_types.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index b4c4a23e77a1..e8047bdbed3a 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -184,8 +184,6 @@ struct paravirt_patch_template { extern struct paravirt_patch_template pv_ops; -#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op) - /* * This generates an indirect call based on the operation type number. * @@ -197,9 +195,20 @@ extern struct paravirt_patch_template pv_ops; * OTOH since this is effectively a __nocfi indirect call, the paravirt stubs * don't need to bother with CFI prefixes. */ +#ifdef CONFIG_X86_64 + +#define paravirt_ptr(array, op) [paravirt_opptr] "i" (&(array.op)) #define PARAVIRT_CALL \ ANNOTATE_RETPOLINE_SAFE "\n\t" \ - "call *%[paravirt_opptr]" + "call *%c[paravirt_opptr](%%rip);" +#else /* CONFIG_X86_32 */ + +#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op) +#define PARAVIRT_CALL \ + ANNOTATE_RETPOLINE_SAFE "\n\t" \ + "call *%[paravirt_opptr];" + +#endif /* CONFIG_X86_64 */ /* * These macros are intended to wrap calls through one of the paravirt -- 2.53.0 李则良 <lizeliang.linux@gmail.com> 于2026年8月14日周五 03:35写道: > > > > > That's not what I asked, now was it. I asked what opcodes it does > > generate. Disassemble an affected function and show the difference > > between the normal -O2 and your -O1 build that causes the failure. > on vmlinux-O1: > (gdb) until arch/x86/kernel/alternative.c:557 > alt_replace_call (instr=0xffffffff82f447e5 <early_fixup_exception+133> > "\377S\b\220\220\353\371[A\\]\303\314\314\314\314\303\314\314\314\314f\017\037D", > insn_buff=0xffffffff82c03d78 <init_thread_union+15736> > "\350\263\177\020\377", > a=0xffffffff831dae0e) at arch/x86/kernel/alternative.c:557 > 557 pr_err("ALT_FLAG_DIRECT_CALL set for unrecognized indirect call\n"); > vmlinux-O1: > 0xffffffff82f447e5 <+133>: ff 53 08 call QWORD PTR [rbx+0x8] > 0xffffffff82f447e8 <+136>: 90 nop > 0xffffffff82f447e9 <+137>: 90 nop > 0xffffffff82f447ea <+138>: eb f9 jmp > 0xffffffff82f447e5 <early_fixup_exception+133> > 0xffffffff82f447ec <+140>: 5b pop rbx > 0xffffffff82f447ed <+141>: 41 5c pop r12 > > vmlinux-O2: > 0xffffffff82f3bf4b <+123>: 74 b0 je > 0xffffffff82f3befd <early_fixup_exception+45> > 0xffffffff82f3bf4d <+125>: eb 08 jmp > 0xffffffff82f3bf57 <early_fixup_exception+135> > 0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR > [rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8> > 0xffffffff82f3bf55 <+133>: eb f8 jmp > 0xffffffff82f3bf4f <early_fixup_exception+127> > 0xffffffff82f3bf57 <+135>: 5b pop rbx > 0xffffffff82f3bf58 <+136>: 41 5c pop r12 > 0xffffffff82f3bf5a <+138>: 5d pop rbp > > I use the patch below to bypass the problem while keeping all logic of > alt_replace_call intact. > > From 2538684697e537298aa9082b582bc7dddd29b278 Mon Sep 17 00:00:00 2001 > From: Zeliang Li <lizeliang.linux@gmail.com> > Date: Fri, 14 Aug 2026 02:32:19 +0800 > Subject: [PATCH] x86/mm: force O2 optimization for early_fixup_exception > > When the kernel is compiled with non-standard optimization flags > (e.g., KCFLAGS=-O1), the function early_fixup_exception may be > compiled to an indirect call instruction that is not recognized > by alt_replace_call() (e.g., "call *0x8(%rbx)"). This triggers a > BUG() during early boot, as seen in: > > ALT_FLAG_DIRECT_CALL: original instruction is not a 6-byte ... > instruction at early_fixup_exception+0x85/0xa0, length=5 > instruction bytes: ff 53 08 90 90 > > Force this function to be compiled with -O2 optimization level, > which guarantees the standard 6-byte `ff 15 <disp32>` form used > by alternatives patching. > > Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com> > --- > arch/x86/mm/extable.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c > index ceb8d03191ab..5d5c7510a817 100644 > --- a/arch/x86/mm/extable.c > +++ b/arch/x86/mm/extable.c > @@ -375,6 +375,7 @@ int fixup_exception(struct pt_regs *regs, int > trapnr, unsigned long error_code, > extern unsigned int early_recursion_flag; > > /* Restricted version used during very early boot */ > +__attribute__((optimize("O2"))) > void __init early_fixup_exception(struct pt_regs *regs, int trapnr) > { > /* Ignore early NMIs. */ > -- > 2.53.0 > > -- > KISS == Keep it simple,stupid~:-) > http://lizeliang.org -- KISS == Keep it simple,stupid~:-) http://lizeliang.org ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] x86/alternatives: gracefully skip unrecognized indirect call instructions 2026-08-13 19:57 ` 李则良 @ 2026-08-14 10:15 ` Jürgen Groß 0 siblings, 0 replies; 12+ messages in thread From: Jürgen Groß @ 2026-08-14 10:15 UTC (permalink / raw) To: 李则良, Peter Zijlstra Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, Kees Cook, Nathan Chancellor, Josh Poimboeuf, linux-kernel [-- Attachment #1.1.1: Type: text/plain, Size: 4614 bytes --] On 13.08.26 21:57, 李则良 wrote: > I am currently testing the more general approach shown below. Your > review is also appreciated. > > on vmlinux-O1: > > 0xffffffff82f447de <+126>: ff 15 a4 a9 cf ff call QWORD PTR > [rip+0xffffffffffcfa9a4] # 0xffffffff82c3f188 <pv_ops+8> > 0xffffffff82f447e4 <+132>: eb f8 jmp > 0xffffffff82f447de <early_fixup_exception+126> > 0xffffffff82f447e6 <+134>: 5b pop rbx > 0xffffffff82f447e7 <+135>: 41 5c pop r12 > 0xffffffff82f447e9 <+137>: 5d pop rbp > > on vmlinux-O2: > > 0xffffffff82f3bf4f <+127>: ff 15 33 32 d0 ff call QWORD PTR > [rip+0xffffffffffd03233] # 0xffffffff82c3f188 <pv_ops+8> > 0xffffffff82f3bf55 <+133>: eb f8 jmp > 0xffffffff82f3bf4f <early_fixup_exception+127> > 0xffffffff82f3bf57 <+135>: 5b pop rbx > 0xffffffff82f3bf58 <+136>: 41 5c pop r12 > 0xffffffff82f3bf5a <+138>: 5d pop rbp > > This is an early draft – please review. Thanks in advance. > > From 5989dcf448e4d23ea4f3a0f91fec34f3dd25d26c Mon Sep 17 00:00:00 2001 > From: Zeliang Li <lizeliang.linux@gmail.com> > Date: Fri, 14 Aug 2026 03:17:38 +0800 > Subject: [PATCH] x86/paravirt: Force RIP-relative paravirt calls under low > optimization levels > > When compiling the kernel with non-standard lower optimization levels like > -O1 (e.g., during specific debugging or framework testing setups) using > newer toolchains like GCC 15.2.0, the compiler exhibits passive register > hoisting. In complex code paths like early_fixup_exception(), it caches the > base address of the global 'pv_ops' structure into a general-purpose register > instead of issuing direct RIP-relative memory loads, producing: > > mov $0xffffffff82c3f180, %rbx > call *0x8(%rbx) > > While this behavior is bypassed under aggressive -O2 optimizations, under -O1 > it leaves a register-relative indirect call. This violates the strict format > assertion in the x86 alternative text-patching engine (alt_replace_call), > which expects an 'ALT_FLAG_DIRECT_CALL' site to be a standard 6-byte > RIP-relative indirect call (ff 15), leading to a boot-time kernel BUG. > > Fix this by changing the x86_64 paravirt inline assembly to use an "i" > (immediate) constraint for the function pointer address, and explicitly > reference it via (%rip) in the assembly template. This removes the > toolchain's ability to select any other addressing mode, guaranteeing the > emission of compliant 'call *pv_ops+offset(%rip)' sequences on x86_64 > regardless of the active compiler -O flag. > > For i386, the original "m" constraint is retained since RIP-relative > addressing does not exist on 32-bit x86. > > Signed-off-by: Zeliang Li <lizeliang.linux@gmail.com> > --- > arch/x86/include/asm/paravirt_types.h | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/include/asm/paravirt_types.h > b/arch/x86/include/asm/paravirt_types.h > index b4c4a23e77a1..e8047bdbed3a 100644 > --- a/arch/x86/include/asm/paravirt_types.h > +++ b/arch/x86/include/asm/paravirt_types.h > @@ -184,8 +184,6 @@ struct paravirt_patch_template { > > extern struct paravirt_patch_template pv_ops; > > -#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op) > - > /* > * This generates an indirect call based on the operation type number. > * > @@ -197,9 +195,20 @@ extern struct paravirt_patch_template pv_ops; > * OTOH since this is effectively a __nocfi indirect call, the paravirt stubs > * don't need to bother with CFI prefixes. > */ > +#ifdef CONFIG_X86_64 > + > +#define paravirt_ptr(array, op) [paravirt_opptr] "i" (&(array.op)) > #define PARAVIRT_CALL \ > ANNOTATE_RETPOLINE_SAFE "\n\t" \ > - "call *%[paravirt_opptr]" > + "call *%c[paravirt_opptr](%%rip);" > +#else /* CONFIG_X86_32 */ > + > +#define paravirt_ptr(array, op) [paravirt_opptr] "m" (array.op) > +#define PARAVIRT_CALL \ > + ANNOTATE_RETPOLINE_SAFE "\n\t" \ > + "call *%[paravirt_opptr];" > + > +#endif /* CONFIG_X86_64 */ > > /* > * These macros are intended to wrap calls through one of the paravirt Thanks for this solution. I like it much more, especially as it will avoid any nasty compiler optimizations as the one you have observed. When sending this as a proper patch you can add my: Reviewed-by: Juergen Gross <jgross@suse.com> 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] 12+ messages in thread
end of thread, other threads:[~2026-08-14 10:15 UTC | newest]
Thread overview: 12+ 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 ` 李则良
2026-08-12 19:01 ` H. Peter Anvin
2026-08-12 19:02 ` H. Peter Anvin
2026-08-13 9:51 ` Peter Zijlstra
2026-08-13 19:35 ` 李则良
2026-08-13 19:57 ` 李则良
2026-08-14 10:15 ` Jürgen Groß
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.