diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 14:08:57 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 14:08:57 -0700 |
| commit | d5b550edadab6810653f287715a0d696306b6ae0 (patch) | |
| tree | be38aaf138393478dd90567260351605c35100f0 /arch/x86/kernel | |
| parent | 3dd1f7447f4f989b3a348cdc347b15397d03bebc (diff) | |
| parent | d824ed1307680dd482f607b0e707c575f70668c4 (diff) | |
Merge tag 'x86-core-2026-08-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 core updates from Ingo Molnar:
- Optimize the kcfi call sequence (Peter Zijlstra)
- Use sfence for wmb() if SSE is available (Yao Zi)
* tag 'x86-core-2026-08-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/locking: Use sfence for wmb() if SSE is available
x86/kcfi: Optimize call sequence
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/alternative.c | 21 | ||||
| -rw-r--r-- | arch/x86/kernel/cfi.c | 11 |
2 files changed, 29 insertions, 3 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 62936a3bde19..ba7d2059a709 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1356,6 +1356,20 @@ early_param("cfi", cfi_parse_cmdline); * "Make conditional jumps most often not taken: The efficiency and throughput * for not-taken branches is better than for taken branches on most * processors. Therefore, it is good to place the most frequent branch first" + * + * NOTE: Update the kCFI caller sequence to make use of this observation: + * + * kCFI kCFI-OPT + * + * caller: caller: + * movl $(-0x12345678),%r10d // 6 movl $(-0x12345678),%r10d // 6 + * addl $-15(%r11),%r10d // 4 addl $-15(%r11),%r10d // 4 + * je 1f // 2 jne . + 3 // 2 + * ud2 // 2 test $0xd6, %al // 2 + * 1: cs call __x86_indirect_thunk_r11 // 6 1: cs call __x86_indirect_thunk_r11 // 6 + * + * This new test clobbers eflags, but those are clobbered by the hash test + * anyway. */ /* @@ -1518,8 +1532,9 @@ static int cfi_disable_callers(s32 *start, s32 *end) static int cfi_enable_callers(s32 *start, s32 *end) { /* - * Re-enable kCFI, undo what cfi_disable_callers() did. + * Re-enable (and update) kCFI, undo what cfi_disable_callers() did. */ + const u8 udne[] = { 0x75, 0x01, 0xa8, 0xd6 }; const u8 mov[] = { 0x41, 0xba }; s32 *s; @@ -1532,6 +1547,10 @@ static int cfi_enable_callers(s32 *start, s32 *end) if (!hash) /* nocfi callers */ continue; + /* + * See the kCFI/FineIBT comment above -- update note. + */ + text_poke_early(addr + 10, udne, 4); text_poke_early(addr, mov, 2); } diff --git a/arch/x86/kernel/cfi.c b/arch/x86/kernel/cfi.c index 638eb5c933e0..1df26dfdce08 100644 --- a/arch/x86/kernel/cfi.c +++ b/arch/x86/kernel/cfi.c @@ -72,8 +72,15 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) switch (cfi_mode) { case CFI_KCFI: - if (!is_cfi_trap(addr)) - return BUG_TRAP_TYPE_NONE; + if (!is_cfi_trap(addr)) { + /* + * The updated kCFI sequence has "test $0xd6, %al" instead of + * "ud2", adjust the offset. + */ + addr -= 1; + if (!is_cfi_trap(addr)) + return BUG_TRAP_TYPE_NONE; + } if (!decode_cfi_insn(regs, &target, &type)) return report_cfi_failure_noaddr(regs, addr); |
