A livepatch module uses klp relocations to reference static functions in vmlinux. If the livepatch module is placed at an address far away from vmlinux, it needs PLT veneers to call those functions.
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 module loader attempts to allocate a page close to the target for emitting a second veneer which has the landing pad along with a direct branch to the target. That page has to come from either the region below _text or the region above _end, as there's no way to allocate memory in the middle of the vmlinux image. For a target near the end of a >128MB text region there's no address space below _text within branch range at all, leaving only whatever room happens to remain above _end after rodata, data and bss. If the branch target is out of range from any available free pages, the livepatch module load fails with -ENOEXEC and a "no address space within branch range" error. Add an assertion so it fails the build instead. Only count the module region below _text; counting the space above _end would make a text size limit depend on the size of rodata, data and bss, and doesn't help unless text is bigger than the rest of the image. The span is _text to _etext rather than __exittext_end, as init and exit text are freed before any module loads and can't be klp targets. Distro kernels don't seem to come close to hitting the 128MB text mark, so this should hopefully be more of a safety backstop than something people are actually hitting. Signed-off-by: Josh Poimboeuf <[email protected]> --- arch/arm64/kernel/vmlinux.lds.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 3a88da9212831..f5bd5ad24e19f 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -419,6 +419,13 @@ ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned") 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 defined(CONFIG_ARM64_BTI_KERNEL) && !defined(CONFIG_COMPILE_TEST) && \ + defined(CONFIG_CC_OMITS_BTI_LANDING_PADS) && defined(CONFIG_LIVEPATCH) +ASSERT(_etext - _text <= SZ_128M - PAGE_SIZE, + "Kernel text too big for BTI live patching") +#endif + /* * If padding is applied before .head.text, virt<->phys conversions will fail. */ -- 2.55.0

