Thread (28 messages) flat view 28 messages, 6 authors, 2026-08-18

Re: [PATCH 02/12] arm64/module: Fix BTI exceptions caused by omitted landing pads in Clang 21

From: Josh Poimboeuf <jpoimboe@kernel.org>
Date: 2026-08-15 18:57:51
Also in: linux-arm-kernel, live-patching, lkml

On Sat, Aug 15, 2026 at 12:56:11PM +0300, Ard Biesheuvel wrote:
Hi Josh,

On Sat, 15 Aug 2026, at 07:45, Josh Poimboeuf wrote:
quoted
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.  But livepatch modules use klp relocations
to reference arbitrary kernel symbols, and with
CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough away that
every call to vmlinux needs a PLT.

Note this problem is actually not specific to livepatch.  It's possible
for any module's .init section to be allocated > 128MB away from its
.text section.  So calls from .init to .text via a PLT can trigger a BTI
exception when the target function doesn't have a landing pad.

GCC has always omitted the landing pad when possible, so kernel BTI is
already considered incompatible with GCC since commit c0a454b9044f
("arm64/bti: Disable in kernel BTI when cross section thunks are
broken").

When missing landing pads are detected, allocate a page close to the
target which can be used to hold BTI veneers which receive PLT veneer
indirect branches and direct branch to the final target:
This does not work for cross-section calls from .init.text to .text.

If .init.text is far away from .text, it is likely because .text
ended up in the 128M 'near' module region, and .init.text did not.
(They tend to end up in direct branching range of each otherwise.)

Given that the module init code is typically small, I don't think
it is safe to assume that allocating a single page close enough to
.text is going to be possible if allocating the space for .init.*
was not.

IOW, the fix I proposed for cross-section calls is still needed
with this approach.
But the BTI veneer page is allocated from a *256MB* window, of which the
near region is only a 128MB subset.

There is a theoretical case where the 256MB window around the target is
completely full without any fragmentation, but I would think that there
would almost always be some fragmentation.  If that window is modules
stacked together, most modules have at least .init.plt and .init.text,
and many have .init.data.

Right now it needs two pages (because of the default guard page) but we
could maybe fall back to VM_NO_GUARD in case of emergency.

-- 
Josh
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help