[PATCH 1/2] arm64: module: Emit BTI veneers for cross-section calls
Ard Biesheuvel
ardb at kernel.org
Thu Aug 13 00:53:34 PDT 2026
On Thu, 13 Aug 2026, at 09:34, Ard Biesheuvel wrote:
> On Thu, 13 Aug 2026, at 00:52, Josh Poimboeuf wrote:
>> On Wed, Aug 12, 2026 at 06:21:00PM +0200, Ard Biesheuvel wrote:
>>> The compiler is permitted to omit BTI landing pads from static functions
>>> that never have their address taken, but are only called directly, even
>>> if those calls originate from other code sections.
>>>
>>> This means that calls into a module's .text section from .init.text,
>>> which may need to be routed via a PLT if .text is out of direct
>>> branching range, may result in BTI exceptions due to the indirect calls
>>> performed by the PLT veneers. (Note that calls to .init.text from .text
>>> are not allowed.)
>>>
>>> The 'solution' is to emit yet another veneer - this is what the ELF
>>> psABI for AArch64 mandates in this case.
>>>
>>> So derive an upper bound for the number of veneers that may be needed in
>>> the core module region to ensure that any call from init code that ends
>>> up needing a PLT can be directed at a veneer with a BTI landing pad, and
>>> allocate the additional space.
>>>
>>> Then, emit these veneers as needed, i.e., only when emitting a PLT entry
>>> for a call from an init code section to a normal code section in the
>>> same module. In practice, this only occurs when a module's .init.text
>>> happens to be allocated far away from its .text section, which might
>>> happen when the initial 128M 'near' module region runs out of space
>>> between allocating the core module and allocating its init region.
>>>
>>> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
>>> ---
>>> arch/arm64/Kconfig | 2 -
>>> arch/arm64/include/asm/module.h | 12 ++
>>> arch/arm64/include/asm/module.lds.h | 3 +
>>> arch/arm64/kernel/module-plts.c | 128 +++++++++++++++++++-
>>> 4 files changed, 138 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index b3afe0688919..25fa80b5591d 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -2114,8 +2114,6 @@ config ARM64_BTI_KERNEL
>>> depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
>>> # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
>>> depends on !CC_IS_GCC || GCC_VERSION >= 100100
>>> - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671
>>> - depends on !CC_IS_GCC
>>
>> This doesn't work for livepatch though, and removing the "depends on
>> !CC_IS_GCC" is a livepatch regression as it broadly increases the
>> likelihood of ARM64_BTI_KERNEL (default y) getting enabled.
>>
>> So "livepatch broken on arm64 clang 21+" now becomes "livepatch broken
>> on arm64".
>>
>
> ... when kernel mode BTI is enabled.
>
> I have no insight into which pieces of livepatch for arm64 are actually
> upstream. Is it just the tooling that is missing? In this case, though,
> I think HAVE_LIVEPATCH should depend on !ARM64_BTI_KERNEL, rather than
> the other way around. I can add that in v2.
>
BTW we may still try and get the compiler folks to add a command line
option to force BTI landing pads to be emitted for static functions, and
enable it for vmlinux only when livepatch is enabled. That way, we can
re-enable kernel mode BTI for all toolchains for the common case, and
have livepatch on arm64 (with BTI) depend on recent versions that implement
this option.
More information about the linux-arm-kernel
mailing list