[AArch64] Landing pad elision breaks kernel mode BTI on Linux
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Commit 7af2b51e761f49974a64c3009882239cea618f2a implements a change to elide BTI landing pads in functions with static linkage that never have their address taken.
This breaks kernel mode BTI on Linux/arm64.
Linux modules are partially linked objects, typically consisting of a `.text` section and a `.init.text` section, the latter of which will be unloaded again once the module is initialized. The allocation strategy for these sections is therefore different, and so these sections are not guaranteed to be within direct branching range of each other. The Linux/arm64 module loader will emit veneers as needed for any direct call that turns out to be out of range when the module is being loaded. These veneers use ADRP/ADD/BR sequences, relying on indirect calls, to create a module address space of 4 GiB (which also contains the core kernel, which is a fully linked ELF executable)
Since modules are not fully linked objects, the static linker stage that emits these special veneers will need to be duplicated in the kernel module loader. This is needed so that indirect calls via veneers to functions that lack a BTI landing pad can be interposed with another veneer that has a landing pad, and performs a direct call to the target.
Adding this logic is rather straight-forward, but it would create some ambiguities for us that we'd like to avoid: Linux relies heavily on code patching, and on arm64, we use `patchable-function-entry` to emit `NOP` instructions into all function prologues. So not only would the veneer code have to duplicate this logic as well, doing so would create confusion about which entrypoint is the true one (or alternatively, all direct calls would have to be routed through the veneer, completely defeating the purpose of this optimization)
For Linux, it would be much better if the heuristic that controls this optimization treated direct calls from different sections as indirect calls, so that in these cases, the BTI landing pad is emitted even though the function has static linkage and is only called directly.
Contributor guide
Research direction
Start with commit 7af2b51e761f49974a64c3009882239cea618f2a and trace the heuristic that elides BTI landing pads for statically linked functions. Examine how calls between the .text and .init.text sections are classified on Linux/arm64. Done means cross-section direct calls retain the BTI landing pad without requiring module-loader veneer changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux
- Domain
- compilers, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100