On a kernel whose text exceeds the +/128MB direct branch range, the linker inserts veneers. With BTI enabled, the veneers' indirect branch targets need a BTI landing pad, which not all functions have starting with Clang 21 (and for all versions of GCC).
In such cases the linker can emit a second veneer close to the target which has the landing pad along with a direct branch to the target. However, that's currently not being done, so GCC and Clang 21+ are broken with BTI on large kernels. Only newer linkers have proper support for adding the second veneer, starting with binutils 2.42 and LLVM 20. Only allow a large kernel with the right combination of compiler and linker. Signed-off-by: Josh Poimboeuf <[email protected]> --- arch/arm64/Kconfig | 7 +++++++ arch/arm64/kernel/vmlinux.lds.S | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b3afe0688919b..2687b71438661 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2123,6 +2123,13 @@ config ARM64_BTI_KERNEL is enabled and the system supports BTI all kernel code including modular code must have BTI enabled. +config CC_OMITS_BTI_LANDING_PADS + def_bool !CC_IS_CLANG || CLANG_VERSION >= 210000 + +config LD_HAS_BTI_STUBS + def_bool (LD_IS_BFD && LD_VERSION >= 24200) || \ + (LD_IS_LLD && LLD_VERSION >= 200000) + config CC_HAS_BRANCH_PROT_PAC_RET_BTI # GCC 9 or later, clang 8 or later def_bool $(cc-option,-mbranch-protection=pac-ret+leaf+bti) diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index af1d720209764..3a88da9212831 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -414,6 +414,11 @@ ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE, #ifdef CONFIG_KVM ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned") #endif + +#if defined(CONFIG_ARM64_BTI_KERNEL) && !defined(CONFIG_COMPILE_TEST) && \ + defined(CONFIG_CC_OMITS_BTI_LANDING_PADS) && !defined(CONFIG_LD_HAS_BTI_STUBS) +ASSERT(__exittext_end - _text <= SZ_128M, "Kernel text too big for BTI") +#endif /* * If padding is applied before .head.text, virt<->phys conversions will fail. */ -- 2.55.0

