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


Reply via email to