Miscellaneous x86 fixes:

- Fix speculative safety in fred_extint()
 
  - Fix __WARN_printf() trap in early_fixup_exception()
 
  - Fix clang-build boot bug for unusual alignments,
    triggered by CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B=y
 
  - Replace the final few __ASSEMBLY__ stragglers that snuck
    in lately into non-UAPI x86 headers and use __ASSEMBLER__
    consistently (again).
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmmkBnwRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1hPpw/+IyRN/VoRYWnqJL/BVCT6PRLhtmc+/+9t
 JLYjCXwDZDf6NGDVOQfeMuubJSt7wSlttPScbQbCSpj1o/xN5AdyBav5jG6fV/PQ
 B9+p+dh4rQSLQR5PHj/PKC9arBSsnBgnTuQKYxCEd/RDc5czNd+tgy6AWsQKS4Ti
 a5xOtsE4xZql49ypOm1JeOu8bZKF+yui6zl8alIE1V1P/dDt9VQ7h7tQB5Dki7Vc
 XVxKOhPAcNpsAa7PXgFihH3g5fqF5WRz1MOvxuVEhlpnJ31LsNhYznUJjwu+VnV0
 0rQDPLs1qs2tq0ysboXh6NVmmjH0ojSQXTlkGsi5Qa4r2EwH0ZcmF74YS9fOzwP2
 V35vGb6Fl0rtZPdQMN0uA6DfiG8+M2yyky71QwoTE27qvbZtXA8wDYn4N2PQa4ZJ
 BJG1MVNzttkxwmRNJa2rg8Uyr7FvG2NVpqJUbFwD87McQtlyv9LUWHw4N8z2nqq9
 3uhj862MCz136zA+jUSR2+zh9aNnx8y/pNMzmwqRAuj5mpH5CK3FZfUlDKWE2YI0
 3tEnbrvL3pv8sIT0/ttyERkCQGBdesHZ5ZaHljb7AUcSVn/Neroo1TZGqrBjyeeV
 kq0w8SHj+BNBs8dNuuy+ONc/Pzk0BMTPpS/flb5qvbCKT655LnCUwIdwy2IIT3XA
 94PISb+ZZQ8=
 =A61U
 -----END PGP SIGNATURE-----

Merge tag 'x86-urgent-2026-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:

 - Fix speculative safety in fred_extint()

 - Fix __WARN_printf() trap in early_fixup_exception()

 - Fix clang-build boot bug for unusual alignments, triggered by
   CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B=y

 - Replace the final few __ASSEMBLY__ stragglers that snuck in lately
   into non-UAPI x86 headers and use __ASSEMBLER__ consistently (again)

* tag 'x86-urgent-2026-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/headers: Replace __ASSEMBLY__ stragglers with __ASSEMBLER__
  x86/cfi: Fix CFI rewrite for odd alignments
  x86/bug: Handle __WARN_printf() trap in early_fixup_exception()
  x86/fred: Correct speculative safety in fred_extint()
This commit is contained in:
Linus Torvalds 2026-03-01 13:16:35 -08:00
commit 5920da4455
12 changed files with 50 additions and 42 deletions

View File

@ -160,8 +160,6 @@ void __init fred_complete_exception_setup(void)
static noinstr void fred_extint(struct pt_regs *regs)
{
unsigned int vector = regs->fred_ss.vector;
unsigned int index = array_index_nospec(vector - FIRST_SYSTEM_VECTOR,
NR_SYSTEM_VECTORS);
if (WARN_ON_ONCE(vector < FIRST_EXTERNAL_VECTOR))
return;
@ -170,7 +168,8 @@ static noinstr void fred_extint(struct pt_regs *regs)
irqentry_state_t state = irqentry_enter(regs);
instrumentation_begin();
sysvec_table[index](regs);
sysvec_table[array_index_nospec(vector - FIRST_SYSTEM_VECTOR,
NR_SYSTEM_VECTORS)](regs);
instrumentation_end();
irqentry_exit(regs, state);
} else {

View File

@ -7,7 +7,7 @@
#include <linux/objtool.h>
#include <asm/asm.h>
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__
struct bug_entry;
extern void __WARN_trap(struct bug_entry *bug, ...);
#endif
@ -137,7 +137,7 @@ do { \
#ifdef HAVE_ARCH_BUG_FORMAT_ARGS
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__
#include <linux/static_call_types.h>
DECLARE_STATIC_CALL(WARN_trap, __WARN_trap);
@ -153,7 +153,7 @@ struct arch_va_list {
struct sysv_va_list args;
};
extern void *__warn_args(struct arch_va_list *args, struct pt_regs *regs);
#endif /* __ASSEMBLY__ */
#endif /* __ASSEMBLER__ */
#define __WARN_bug_entry(flags, format) ({ \
struct bug_entry *bug; \

View File

@ -111,6 +111,12 @@ extern bhi_thunk __bhi_args_end[];
struct pt_regs;
#ifdef CONFIG_CALL_PADDING
#define CFI_OFFSET (CONFIG_FUNCTION_PADDING_CFI+5)
#else
#define CFI_OFFSET 5
#endif
#ifdef CONFIG_CFI
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
#define __bpfcall
@ -119,11 +125,9 @@ static inline int cfi_get_offset(void)
{
switch (cfi_mode) {
case CFI_FINEIBT:
return 16;
return /* fineibt_prefix_size */ 16;
case CFI_KCFI:
if (IS_ENABLED(CONFIG_CALL_PADDING))
return 16;
return 5;
return CFI_OFFSET;
default:
return 0;
}

View File

@ -77,7 +77,7 @@ static __always_inline void native_local_irq_restore(unsigned long flags)
#endif
#ifndef CONFIG_PARAVIRT
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__
/*
* Used in the idle loop; sti takes one instruction cycle
* to complete:
@ -95,7 +95,7 @@ static __always_inline void halt(void)
{
native_halt();
}
#endif /* __ASSEMBLY__ */
#endif /* __ASSEMBLER__ */
#endif /* CONFIG_PARAVIRT */
#ifdef CONFIG_PARAVIRT_XXL

View File

@ -68,7 +68,7 @@
* Depending on -fpatchable-function-entry=N,N usage (CONFIG_CALL_PADDING) the
* CFI symbol layout changes.
*
* Without CALL_THUNKS:
* Without CALL_PADDING:
*
* .align FUNCTION_ALIGNMENT
* __cfi_##name:
@ -77,7 +77,7 @@
* .long __kcfi_typeid_##name
* name:
*
* With CALL_THUNKS:
* With CALL_PADDING:
*
* .align FUNCTION_ALIGNMENT
* __cfi_##name:

View File

@ -20,7 +20,7 @@
#define PER_CPU_VAR(var) __percpu(var)__percpu_rel
#else /* !__ASSEMBLY__: */
#else /* !__ASSEMBLER__: */
#include <linux/args.h>
#include <linux/bits.h>

View File

@ -6,7 +6,7 @@
#error "Cannot use runtime-const infrastructure from modules"
#endif
#ifdef __ASSEMBLY__
#ifdef __ASSEMBLER__
.macro RUNTIME_CONST_PTR sym reg
movq $0x0123456789abcdef, %\reg
@ -16,7 +16,7 @@
.popsection
.endm
#else /* __ASSEMBLY__ */
#else /* __ASSEMBLER__ */
#define runtime_const_ptr(sym) ({ \
typeof(sym) __ret; \
@ -74,5 +74,5 @@ static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
}
}
#endif /* __ASSEMBLY__ */
#endif /* __ASSEMBLER__ */
#endif

View File

@ -25,6 +25,8 @@ extern int ibt_selftest_noendbr(void);
void handle_invalid_op(struct pt_regs *regs);
#endif
noinstr bool handle_bug(struct pt_regs *regs);
static inline int get_si_code(unsigned long condition)
{
if (condition & DR_STEP)

View File

@ -1182,7 +1182,7 @@ void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
poison_endbr(addr);
if (IS_ENABLED(CONFIG_FINEIBT))
poison_cfi(addr - 16);
poison_cfi(addr - CFI_OFFSET);
}
}
@ -1389,6 +1389,8 @@ extern u8 fineibt_preamble_end[];
#define fineibt_preamble_ud 0x13
#define fineibt_preamble_hash 5
#define fineibt_prefix_size (fineibt_preamble_size - ENDBR_INSN_SIZE)
/*
* <fineibt_caller_start>:
* 0: b8 78 56 34 12 mov $0x12345678, %eax
@ -1634,7 +1636,7 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
* have determined there are no indirect calls to it and we
* don't need no CFI either.
*/
if (!is_endbr(addr + 16))
if (!is_endbr(addr + CFI_OFFSET))
continue;
hash = decode_preamble_hash(addr, &arity);
@ -1642,6 +1644,15 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
addr, addr, 5, addr))
return -EINVAL;
/*
* FineIBT relies on being at func-16, so if the preamble is
* actually larger than that, place it the tail end.
*
* NOTE: this is possible with things like DEBUG_CALL_THUNKS
* and DEBUG_FORCE_FUNCTION_ALIGN_64B.
*/
addr += CFI_OFFSET - fineibt_prefix_size;
text_poke_early(addr, fineibt_preamble_start, fineibt_preamble_size);
WARN_ON(*(u32 *)(addr + fineibt_preamble_hash) != 0x12345678);
text_poke_early(addr + fineibt_preamble_hash, &hash, 4);
@ -1664,10 +1675,10 @@ static void cfi_rewrite_endbr(s32 *start, s32 *end)
for (s = start; s < end; s++) {
void *addr = (void *)s + *s;
if (!exact_endbr(addr + 16))
if (!exact_endbr(addr + CFI_OFFSET))
continue;
poison_endbr(addr + 16);
poison_endbr(addr + CFI_OFFSET);
}
}
@ -1772,7 +1783,8 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
if (FINEIBT_WARN(fineibt_preamble_size, 20) ||
FINEIBT_WARN(fineibt_preamble_bhi + fineibt_bhi1_size, 20) ||
FINEIBT_WARN(fineibt_caller_size, 14) ||
FINEIBT_WARN(fineibt_paranoid_size, 20))
FINEIBT_WARN(fineibt_paranoid_size, 20) ||
WARN_ON_ONCE(CFI_OFFSET < fineibt_prefix_size))
return;
if (cfi_mode == CFI_AUTO) {
@ -1885,6 +1897,11 @@ static void poison_cfi(void *addr)
*/
switch (cfi_mode) {
case CFI_FINEIBT:
/*
* FineIBT preamble is at func-16.
*/
addr += CFI_OFFSET - fineibt_prefix_size;
/*
* FineIBT prefix should start with an ENDBR.
*/
@ -1923,8 +1940,6 @@ static void poison_cfi(void *addr)
}
}
#define fineibt_prefix_size (fineibt_preamble_size - ENDBR_INSN_SIZE)
/*
* When regs->ip points to a 0xD6 byte in the FineIBT preamble,
* return true and fill out target and type.

View File

@ -397,7 +397,7 @@ static inline void handle_invalid_op(struct pt_regs *regs)
ILL_ILLOPN, error_get_trap_addr(regs));
}
static noinstr bool handle_bug(struct pt_regs *regs)
noinstr bool handle_bug(struct pt_regs *regs)
{
unsigned long addr = regs->ip;
bool handled = false;

View File

@ -411,14 +411,11 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
return;
if (trapnr == X86_TRAP_UD) {
if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
/* Skip the ud2. */
regs->ip += LEN_UD2;
if (handle_bug(regs))
return;
}
/*
* If this was a BUG and report_bug returns or if this
* If this was a BUG and handle_bug returns or if this
* was just a normal #UD, we want to continue onward and
* crash.
*/

View File

@ -438,17 +438,8 @@ static void emit_kcfi(u8 **pprog, u32 hash)
EMIT1_off32(0xb8, hash); /* movl $hash, %eax */
#ifdef CONFIG_CALL_PADDING
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
EMIT1(0x90);
for (int i = 0; i < CONFIG_FUNCTION_PADDING_CFI; i++)
EMIT1(0x90);
#endif
EMIT_ENDBR();