(cc Kees, Nick)
On Mon, 10 Aug 2026, at 17:48, Josh Poimboeuf wrote: > On Mon, Aug 10, 2026 at 11:31:10AM +0100, Will Deacon wrote: >> On Fri, Aug 07, 2026 at 02:46:11PM -0700, Josh Poimboeuf wrote: >> > The following BTI exception was seen when loading a livepatch module: >> > >> > Internal error: Oops - BTI: 0000000036000001 [#1] SMP >> > pstate: 634004c9 (nZCv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=jc) >> > pc : kill_orphaned_pgrp+0x0/0x150 >> > lr : do_exit+0x498/0xaf0 [livepatch_combined] >> > >> > The problem is that the patch module's do_exit() is branching to a >> > static function in vmlinux using a module PLT veneer (indirect branch), >> > but the target function doesn't have a BTI landing pad. >> > >> > Clang 21+ omits the landing pad for static functions which can only be >> > reached by a direct branch. That's fine for ordinary modules which only >> > branch to global exported functions. But livepatch modules use klp >> > relocations to reference arbitrary kernel symbols, and with >> > CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough from the >> > kernel that every R_AARCH64_CALL26 needs a PLT. >> > >> > RET is exempt from BTI checking, so use it instead of BR when the target >> > has no landing pad, similar to what ftrace and BPF do. >> >> Hmm, doesn't that somewhat undermine the purpose of using BTI in the >> kernel? Now we're going to create PLTs that can branch to arbitrary >> addresses. > > Yes, but just to clarify: > > - Only with livepatch modules loaded (and we can add an > is_livepatch_module() check). > > - Only a small minority of livepatch klp relocations need it. > > - There are already other instances of "ret <reg>" in the kernel in > ftrace, BPF, and kvm. > >> > This was found by testing with klp-build and Clang 21, but the issue is >> > not specific to klp-build. It's inherent to any livepatch module use of >> > klp relocations. >> > >> > Previous tests with Clang 20 did not show this problem, as older Clang >> > unconditionally emits "bti c" for every C function. >> >> Is there an option to restore that behaviour if CONFIG_LIVEPATCH=y? >> Otherwise, I think I'd be more inclined to add yet-another dependency >> to CONFIG_ARM64_BTI_KERNEL so it's disabled if LIVEPATCH is selected. > > Hm, looking deeper, is BTI just fundamentally broken now, independent of > livepatch? > > config ARM64_BTI_KERNEL > ... > # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671 > depends on !CC_IS_GCC > ... > > AFAICT, the reason for the "depends on !CC_IS_GCC" is that GCC was > already doing the exact same thing Clang is now doing: namely, omitting > BTI for static functions that don't have a pointer taken to them. > > So Clang 21+ now has the original GCC edge case: an .init.text direct > branching to a .text function which happens to be allocated >= 128MB > away and which doesn't have BTI. > > In which case I think to properly support BTI going forward we would > need two "veneers"? Either that or remove BTI kernel support > altogether. > Yeah, it seems we did not argue our case convincingly: their assumption that veneers/PLTs can be placed within -/+ 128M of their target does not hold for us. But I don't think it holds for .text sections larger than 128M either, so I'm not convinced their reasoning is sound even for the general case. I suppose we could special-case the PLT logic to use direct branches where possible, which would probably catch most of these (assuming .text and .init.text tend to end up close to each other also for KLP modules) For the remaining cases, we'd indeed need a second veneer at the callee end (i.e., inside .text in this case) that is emitted when resolving a cross-section indirect call to a function that lacks the BTI landing pad. But that would be its sole purpose, so I don't think we should go down this route. Instead, the 'address taken' check should include 'called directly from a different section'. Emitting veneers to work around a compiler optimization is just plain silly. I'll try and poke people on the Clang side of things to revisit this. I guess that leaves kernel BTI broken for the foreseeable future but so be it.

