freenode
Kernel & Low-Level

Linux disables arm64 in-kernel BTI on Clang 21 over livepatch crash

A Clang 21 change that drops landing pads on static functions breaks PLT branches from livepatch modules, so the kernel turns BTI off until the toolchain is fixed.

Kernel developers are disabling in-kernel Branch Target Identification (BTI) on arm64 when building with Clang 21 or newer after livepatch modules began crashing with BTI exceptions.

Josh Poimboeuf hit the failure while testing livepatch with Clang 21. A patched function branched through a module PLT veneer to a static function in the main kernel image, and that target had no BTI landing pad. Clang 21 and later omit those pads for static functions that the compiler believes are only reached by direct calls. That is usually safe for ordinary modules, which only call exported globals. Livepatch modules are different: they use klp relocations against arbitrary kernel symbols, and with full module-region randomization they sit far enough from vmlinux that long-range calls go through PLTs, which are indirect branches and therefore require landing pads.

Poimboeuf first proposed teaching the arm64 PLT code to use a return-style branch when the target lacks a pad, matching what ftrace and BPF already do. Will Deacon objected that this would weaken BTI by allowing PLTs to jump to arbitrary addresses. Mark Brown added that the problem is not livepatch-only: the same crash can appear when modules place related functions in different sections that end up far apart, an issue GCC already triggers.

The agreed short-term fix is to put Clang 21+ in the same category as GCC and refuse CONFIG_ARM64_BTI_KERNEL until the compilers emit usable pads again. Ard Biesheuvel opened LLVM issue 215547 to push for a toolchain change (or an opt-in flag), and Will Deacon prepared the Kconfig patch under Poimboeuf's authorship. Nick Desaulniers noted that the blanket disable also costs BTI on Clang-built kernels that never enable livepatch, including Android configurations; Poimboeuf replied that livepatch only makes the failure easy to hit, and the underlying section-distance problem remains either way.

Until Clang (and GCC) treat cross-section and livepatch-style calls as needing landing pads, arm64 kernels built with current mainline Clang lose in-kernel BTI.