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. That's fine for ordinary modules which only
branch to global exported functions. But livepatch modules use klp
relocations to reference arbitrary kernel symbols, and with
CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough from the
kernel that every R_AARCH64_CALL26 needs a PLT.
RET is exempt from BTI checking, so use it instead of BR when the target
has no landing pad, similar to what ftrace and BPF do.
This was found by testing with klp-build and Clang 21, but the issue is
not specific to klp-build. It's inherent to any livepatch module use of
klp relocations.
Previous tests with Clang 20 did not show this problem, as older Clang
unconditionally emits "bti c" for every C function.
Fixes: fd1e0fd71f65 ("arm64: Implement HAVE_LIVEPATCH")
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
arch/arm64/kernel/module-plts.c | 42 +++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 4 deletions(-)
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Direct assignment to read-only memory in `module_emit_plt_entry()` and `module_emit_veneer_for_adrp()` causes a Data Abort kernel panic when resolving livepatch delayed relocations, and misses instruction cache flushing.
--
commit b15500d2c41dfd08d4a46e3f6cffc977c910f40a
Author: Josh Poimboeuf [off-list ref]
arm64/module: Fix livepatch BTI exceptions with Clang 21+
This commit fixes a BTI exception during livepatch module loading by using
RET instead of BR when branching to static functions that lack a BTI landing
pad. It introduces a check for landing pads and adjusts the branch
instruction emitted by get_plt_entry().
[Severity: High]
This is a pre-existing issue, but does direct assignment to the PLT memory
region cause a Data Abort when livepatch resolves delayed relocations?
When a target module is loaded after a livepatch is active,
apply_relocate_add() calls module_emit_plt_entry() on the livepatch module.
Because the livepatch module is already in a live state, its .plt section
has been marked read-only via strict_module_rwx().
Looking at module_emit_plt_entry() in arch/arm64/kernel/module-plts.c:
module_emit_plt_entry() {
...
plt[i] = get_plt_entry(val, &plt[i]);
...
}
And similarly in module_emit_veneer_for_adrp():
module_emit_veneer_for_adrp() {
...
plt[i] = __get_adrp_add_pair(val, (u64)&plt[i], rd);
plt[i].br = cpu_to_le32(br);
...
}
Since this direct assignment bypasses __text_poke() or aarch64_insn_copy(),
does it trigger a panic due to writing to read-only memory, and also fail
to flush the instruction cache for the newly emitted PLT entry?
--
Sashiko AI review · https://sashiko.dev/#/patchset/ed4fe1f95071897859ec7fbe9176246cbd4962bf.1786138806.git.jpoimboe@kernel.org?part=1
From: Will Deacon <will@kernel.org> Date: 2026-08-10 10:31:29
On Fri, Aug 07, 2026 at 02:46:11PM -0700, Josh Poimboeuf wrote:
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. That's fine for ordinary modules which only
branch to global exported functions. But livepatch modules use klp
relocations to reference arbitrary kernel symbols, and with
CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough from the
kernel that every R_AARCH64_CALL26 needs a PLT.
RET is exempt from BTI checking, so use it instead of BR when the target
has no landing pad, similar to what ftrace and BPF do.
Hmm, doesn't that somewhat undermine the purpose of using BTI in the
kernel? Now we're going to create PLTs that can branch to arbitrary
addresses.
This was found by testing with klp-build and Clang 21, but the issue is
not specific to klp-build. It's inherent to any livepatch module use of
klp relocations.
Previous tests with Clang 20 did not show this problem, as older Clang
unconditionally emits "bti c" for every C function.
Is there an option to restore that behaviour if CONFIG_LIVEPATCH=y?
Otherwise, I think I'd be more inclined to add yet-another dependency
to CONFIG_ARM64_BTI_KERNEL so it's disabled if LIVEPATCH is selected.
Will
On Mon, Aug 10, 2026 at 11:31:10AM +0100, Will Deacon wrote:
On Fri, Aug 07, 2026 at 02:46:11PM -0700, 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. That's fine for ordinary modules which only
branch to global exported functions. But livepatch modules use klp
relocations to reference arbitrary kernel symbols, and with
CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough from the
kernel that every R_AARCH64_CALL26 needs a PLT.
RET is exempt from BTI checking, so use it instead of BR when the target
has no landing pad, similar to what ftrace and BPF do.
Hmm, doesn't that somewhat undermine the purpose of using BTI in the
kernel? Now we're going to create PLTs that can branch to arbitrary
addresses.
Yes, but just to clarify:
- Only with livepatch modules loaded (and we can add an
is_livepatch_module() check).
- Only a small minority of livepatch klp relocations need it.
- There are already other instances of "ret <reg>" in the kernel in
ftrace, BPF, and kvm.
quoted
This was found by testing with klp-build and Clang 21, but the issue is
not specific to klp-build. It's inherent to any livepatch module use of
klp relocations.
Previous tests with Clang 20 did not show this problem, as older Clang
unconditionally emits "bti c" for every C function.
Is there an option to restore that behaviour if CONFIG_LIVEPATCH=y?
Otherwise, I think I'd be more inclined to add yet-another dependency
to CONFIG_ARM64_BTI_KERNEL so it's disabled if LIVEPATCH is selected.
Hm, looking deeper, is BTI just fundamentally broken now, independent of
livepatch?
config ARM64_BTI_KERNEL
...
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671
depends on !CC_IS_GCC
...
AFAICT, the reason for the "depends on !CC_IS_GCC" is that GCC was
already doing the exact same thing Clang is now doing: namely, omitting
BTI for static functions that don't have a pointer taken to them.
So Clang 21+ now has the original GCC edge case: an .init.text direct
branching to a .text function which happens to be allocated >= 128MB
away and which doesn't have BTI.
In which case I think to properly support BTI going forward we would
need two "veneers"? Either that or remove BTI kernel support
altogether.
--
Josh
(cc Kees, Nick)
On Mon, 10 Aug 2026, at 17:48, Josh Poimboeuf wrote:
On Mon, Aug 10, 2026 at 11:31:10AM +0100, Will Deacon wrote:
quoted
On Fri, Aug 07, 2026 at 02:46:11PM -0700, 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. That's fine for ordinary modules which only
branch to global exported functions. But livepatch modules use klp
relocations to reference arbitrary kernel symbols, and with
CONFIG_RANDOMIZE_MODULE_REGION_FULL the module is far enough from the
kernel that every R_AARCH64_CALL26 needs a PLT.
RET is exempt from BTI checking, so use it instead of BR when the target
has no landing pad, similar to what ftrace and BPF do.
Hmm, doesn't that somewhat undermine the purpose of using BTI in the
kernel? Now we're going to create PLTs that can branch to arbitrary
addresses.
Yes, but just to clarify:
- Only with livepatch modules loaded (and we can add an
is_livepatch_module() check).
- Only a small minority of livepatch klp relocations need it.
- There are already other instances of "ret <reg>" in the kernel in
ftrace, BPF, and kvm.
quoted
quoted
This was found by testing with klp-build and Clang 21, but the issue is
not specific to klp-build. It's inherent to any livepatch module use of
klp relocations.
Previous tests with Clang 20 did not show this problem, as older Clang
unconditionally emits "bti c" for every C function.
Is there an option to restore that behaviour if CONFIG_LIVEPATCH=y?
Otherwise, I think I'd be more inclined to add yet-another dependency
to CONFIG_ARM64_BTI_KERNEL so it's disabled if LIVEPATCH is selected.
Hm, looking deeper, is BTI just fundamentally broken now, independent of
livepatch?
config ARM64_BTI_KERNEL
...
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671
depends on !CC_IS_GCC
...
AFAICT, the reason for the "depends on !CC_IS_GCC" is that GCC was
already doing the exact same thing Clang is now doing: namely, omitting
BTI for static functions that don't have a pointer taken to them.
So Clang 21+ now has the original GCC edge case: an .init.text direct
branching to a .text function which happens to be allocated >= 128MB
away and which doesn't have BTI.
In which case I think to properly support BTI going forward we would
need two "veneers"? Either that or remove BTI kernel support
altogether.
Yeah, it seems we did not argue our case convincingly: their assumption
that veneers/PLTs can be placed within -/+ 128M of their target does not
hold for us. But I don't think it holds for .text sections larger than
128M either, so I'm not convinced their reasoning is sound even for the
general case.
I suppose we could special-case the PLT logic to use direct branches
where possible, which would probably catch most of these (assuming
.text and .init.text tend to end up close to each other also for KLP
modules)
For the remaining cases, we'd indeed need a second veneer at the callee
end (i.e., inside .text in this case) that is emitted when resolving a
cross-section indirect call to a function that lacks the BTI landing
pad. But that would be its sole purpose, so I don't think we should go
down this route. Instead, the 'address taken' check should include 'called
directly from a different section'. Emitting veneers to work around a
compiler optimization is just plain silly.
I'll try and poke people on the Clang side of things to revisit this.
I guess that leaves kernel BTI broken for the foreseeable future but so
be it.
This was found by testing with klp-build and Clang 21, but the issue is
not specific to klp-build. It's inherent to any livepatch module use of
klp relocations.
quoted
Previous tests with Clang 20 did not show this problem, as older Clang
unconditionally emits "bti c" for every C function.
Is there an option to restore that behaviour if CONFIG_LIVEPATCH=y?
Otherwise, I think I'd be more inclined to add yet-another dependency
to CONFIG_ARM64_BTI_KERNEL so it's disabled if LIVEPATCH is selected.
This won't even be livepatch specific I think - I expect the same issue
can be triggered for module loading by using annotations to place
functions from the same translation unit in different sections if the
sections get placed far enough apart. That was what was impacting GCC.
On Mon, Aug 10, 2026 at 06:12:10PM +0200, Ard Biesheuvel wrote:
On Mon, 10 Aug 2026, at 17:48, Josh Poimboeuf wrote:
quoted
In which case I think to properly support BTI going forward we would
need two "veneers"? Either that or remove BTI kernel support
altogether.
Yeah, it seems we did not argue our case convincingly: their assumption
that veneers/PLTs can be placed within -/+ 128M of their target does not
hold for us. But I don't think it holds for .text sections larger than
128M either, so I'm not convinced their reasoning is sound even for the
general case.
I suppose we could special-case the PLT logic to use direct branches
where possible, which would probably catch most of these (assuming
.text and .init.text tend to end up close to each other also for KLP
modules)
For the remaining cases, we'd indeed need a second veneer at the callee
end (i.e., inside .text in this case) that is emitted when resolving a
cross-section indirect call to a function that lacks the BTI landing
pad. But that would be its sole purpose, so I don't think we should go
down this route. Instead, the 'address taken' check should include 'called
directly from a different section'. Emitting veneers to work around a
compiler optimization is just plain silly.
I'll try and poke people on the Clang side of things to revisit this.
I guess that leaves kernel BTI broken for the foreseeable future but so
be it.
Ok, so for now I suppose we need something like so?
From: Nick Desaulniers <ndesaulniers@google.com> Date: 2026-08-10 16:42:04
On Mon, Aug 10, 2026 at 9:39 AM Josh Poimboeuf [off-list ref] wrote:
quoted hunk
On Mon, Aug 10, 2026 at 06:12:10PM +0200, Ard Biesheuvel wrote:
quoted
On Mon, 10 Aug 2026, at 17:48, Josh Poimboeuf wrote:
quoted
In which case I think to properly support BTI going forward we would
need two "veneers"? Either that or remove BTI kernel support
altogether.
Yeah, it seems we did not argue our case convincingly: their assumption
that veneers/PLTs can be placed within -/+ 128M of their target does not
hold for us. But I don't think it holds for .text sections larger than
128M either, so I'm not convinced their reasoning is sound even for the
general case.
I suppose we could special-case the PLT logic to use direct branches
where possible, which would probably catch most of these (assuming
.text and .init.text tend to end up close to each other also for KLP
modules)
For the remaining cases, we'd indeed need a second veneer at the callee
end (i.e., inside .text in this case) that is emitted when resolving a
cross-section indirect call to a function that lacks the BTI landing
pad. But that would be its sole purpose, so I don't think we should go
down this route. Instead, the 'address taken' check should include 'called
directly from a different section'. Emitting veneers to work around a
compiler optimization is just plain silly.
I'll try and poke people on the Clang side of things to revisit this.
I guess that leaves kernel BTI broken for the foreseeable future but so
be it.
Ok, so for now I suppose we need something like so?
Sure, but let's replace this with a link to a bug report in llvm's
issue tracker? I meet with Arm's toolchain team (of which Simon
is...on or adjacent to). I can bring this up then.
quoted hunk
+ depends on !CC_IS_CLANG || CLANG_VERSION < 210000 depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_ARGS) help Build the kernel with Branch Target Identification annotations
From: Will Deacon <will@kernel.org> Date: 2026-08-11 09:45:01
On Mon, Aug 10, 2026 at 09:41:35AM -0700, Nick Desaulniers wrote:
On Mon, Aug 10, 2026 at 9:39 AM Josh Poimboeuf [off-list ref] wrote:
quoted
On Mon, Aug 10, 2026 at 06:12:10PM +0200, Ard Biesheuvel wrote:
quoted
On Mon, 10 Aug 2026, at 17:48, Josh Poimboeuf wrote:
quoted
In which case I think to properly support BTI going forward we would
need two "veneers"? Either that or remove BTI kernel support
altogether.
Yeah, it seems we did not argue our case convincingly: their assumption
that veneers/PLTs can be placed within -/+ 128M of their target does not
hold for us. But I don't think it holds for .text sections larger than
128M either, so I'm not convinced their reasoning is sound even for the
general case.
I suppose we could special-case the PLT logic to use direct branches
where possible, which would probably catch most of these (assuming
.text and .init.text tend to end up close to each other also for KLP
modules)
For the remaining cases, we'd indeed need a second veneer at the callee
end (i.e., inside .text in this case) that is emitted when resolving a
cross-section indirect call to a function that lacks the BTI landing
pad. But that would be its sole purpose, so I don't think we should go
down this route. Instead, the 'address taken' check should include 'called
directly from a different section'. Emitting veneers to work around a
compiler optimization is just plain silly.
I'll try and poke people on the Clang side of things to revisit this.
I guess that leaves kernel BTI broken for the foreseeable future but so
be it.
Ok, so for now I suppose we need something like so?
Sure, but let's replace this with a link to a bug report in llvm's
issue tracker? I meet with Arm's toolchain team (of which Simon
is...on or adjacent to). I can bring this up then.
Yes, please! I can apply the patch once we have the bug number.
Will
Thanks, Ard. I've ended up with the patch below.
Will
--->8
Author: Josh Poimboeuf [off-list ref]
Date: Tue Aug 11 14:11:44 2026 +0000
arm64: bti: Disable in-kernel BTI with recent versions of Clang
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. That's normally fine for ordinary modules
which only branch to global exported functions, but Mark Brown points
out [1] that this isn't guaranteed if the module branches between
sections. Futhermore, livepatch modules use klp relocations to reference
arbitrary kernel symbols, so with CONFIG_RANDOMIZE_MODULE_REGION_FULL
the module is far enough from the kernel that every R_AARCH64_CALL26
needs a PLT.
Put Clang 21+ in the naughty corner alongside GCC, which suffers from
the same issue, by disabling CONFIG_ARM64_BTI_KERNEL until we have a
version of the toolchain with the problem resolved.
Cc: Ard Biesheuvel [off-list ref]
Link: https://lore.kernel.org/r/da06bbd3-d04b-4d0f-b331-f5b91bc373a5@sirena.org.uk [1]
Fixes: fd1e0fd71f65 ("arm64: Implement HAVE_LIVEPATCH")
Signed-off-by: Josh Poimboeuf [off-list ref]
[will: Stitched together commit message, diff and bug number]
Signed-off-by: Will Deacon [off-list ref]
Author: Josh Poimboeuf [off-list ref]
Date: Tue Aug 11 14:11:44 2026 +0000
arm64: bti: Disable in-kernel BTI with recent versions of Clang
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.
I had missed this bit before, i.e., the fact that the target is a static
function inside vmlinux.
The lack of a BTI landing pad suggests that the address of this function
is never taken either, and so the symbol in question is not exported to
modules, right?
Does KLP make any special accommodations to ensure that this is safe? Otherwise,
BTI is not the only potential issue: the compiler may apply interprocedural
optimizations, and the function in question may not be AAPCS64 compliant as
a result.
It also means treating cross-section jumps as indirect calls in the BTI
landing pad elision heuristic would not work around the issue here.
On Tue, Aug 11, 2026 at 04:55:37PM +0200, Ard Biesheuvel wrote:
On Tue, 11 Aug 2026, at 16:23, Will Deacon wrote:
quoted
Author: Josh Poimboeuf [off-list ref]
Date: Tue Aug 11 14:11:44 2026 +0000
arm64: bti: Disable in-kernel BTI with recent versions of Clang
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.
I had missed this bit before, i.e., the fact that the target is a static
function inside vmlinux.
The lack of a BTI landing pad suggests that the address of this function
is never taken either, and so the symbol in question is not exported to
modules, right?
Does KLP make any special accommodations to ensure that this is safe? Otherwise,
BTI is not the only potential issue: the compiler may apply interprocedural
optimizations, and the function in question may not be AAPCS64 compliant as
a result.
It also means treating cross-section jumps as indirect calls in the BTI
landing pad elision heuristic would not work around the issue here.
Yes, the livepatch module creation process takes interprocedural
optimizations into account.
With kpatch-build and the new in-tree klp-build (x86 only, arm64 coming
soon), it does a binary diff between the old and new kernels, and
extracts the changed functions. So if the interface between caller and
callee changes, they both get patched.
--
Josh
Thanks.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671 was closed as
invalid pointing to the same commit in llvm. What's going on here?
Where's the corresponding feature request for GCC?
At the least, I could imagine there being a `-fno-omit-bti-pads` or
whatever for the kernel to opt into this behavior.
--
Thanks,
~Nick Desaulniers
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
quoted hunk
Will
--->8
Author: Josh Poimboeuf [off-list ref]
Date: Tue Aug 11 14:11:44 2026 +0000
arm64: bti: Disable in-kernel BTI with recent versions of Clang
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. That's normally fine for ordinary modules
which only branch to global exported functions, but Mark Brown points
out [1] that this isn't guaranteed if the module branches between
sections. Futhermore, livepatch modules use klp relocations to reference
arbitrary kernel symbols, so with CONFIG_RANDOMIZE_MODULE_REGION_FULL
the module is far enough from the kernel that every R_AARCH64_CALL26
needs a PLT.
Put Clang 21+ in the naughty corner alongside GCC, which suffers from
the same issue, by disabling CONFIG_ARM64_BTI_KERNEL until we have a
version of the toolchain with the problem resolved.
Cc: Ard Biesheuvel [off-list ref]
Link: https://lore.kernel.org/r/da06bbd3-d04b-4d0f-b331-f5b91bc373a5@sirena.org.uk [1]
Fixes: fd1e0fd71f65 ("arm64: Implement HAVE_LIVEPATCH")
Signed-off-by: Josh Poimboeuf [off-list ref]
[will: Stitched together commit message, diff and bug number]
Signed-off-by: Will Deacon [off-list ref]
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
The problem isn't specific to livepatch, livepatch just makes it easier
to hit.
--
Josh
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
The problem isn't specific to livepatch, livepatch just makes it easier
to hit.
Rereading Ard's report, let me see if I can articulate _how_ and tell
me if I'm still not getting it.
Let's say we have code in .init.text that calls code in .text. If
.text was placed large enough away from .init.text, we get a veneer
inserted by _the kernel_ (not the linker). This veneer has an
indirect call to the destination. No landing pad. Boom.
Is that precise?
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
The problem isn't specific to livepatch, livepatch just makes it easier
to hit.
Rereading Ard's report, let me see if I can articulate _how_ and tell
me if I'm still not getting it.
Let's say we have code in .init.text that calls code in .text. If
.text was placed large enough away from .init.text, we get a veneer
inserted by _the kernel_ (not the linker). This veneer has an
indirect call to the destination. No landing pad. Boom.
Is that precise?
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
The problem isn't specific to livepatch, livepatch just makes it easier
to hit.
Rereading Ard's report, let me see if I can articulate _how_ and tell
me if I'm still not getting it.
Let's say we have code in .init.text that calls code in .text. If
.text was placed large enough away from .init.text, we get a veneer
inserted by _the kernel_ (not the linker). This veneer has an
indirect call to the destination. No landing pad. Boom.
Is that precise?
Yes.
Naive question: Could the machinery that emits the veneer instead emit
N veneers, one for each cross section reference? Rather than one
veneer that could branch indirectly to N destinations (that probably
don't have landing pads), could we instead have N veneers that branch
directly to 1 location each? Are the veneers larger than just a
branch? Is the destination unknown when the veneers are created? This
would retain the landing pad elision optimization for .text (which is
likely run more frequently than .init.text), and you could probably
put those veneers in .init.text and throw them away with the rest of
__init.
--
Thanks,
~Nick Desaulniers
What's the extent that HAVE_LIVEPATCH will be used?
Does this penalize kernels built with BTI in favor of HAVE_LIVEPATCH?
For example, with my Android hat on, if we have a kernel that's built
with ARM64_BTI_KERNEL=y, and _dont_ use HAVE_LIVEPATCH, we're going to
turn off BTI for a feature we're not using? But maybe we _do_ intend
to use HAVE_LIVEPATCH, and my assumption was wrong?
The problem isn't specific to livepatch, livepatch just makes it easier
to hit.
Rereading Ard's report, let me see if I can articulate _how_ and tell
me if I'm still not getting it.
Let's say we have code in .init.text that calls code in .text. If
.text was placed large enough away from .init.text, we get a veneer
inserted by _the kernel_ (not the linker). This veneer has an
indirect call to the destination. No landing pad. Boom.
Is that precise?
Yes.
Naive question: Could the machinery that emits the veneer instead emit
N veneers, one for each cross section reference? Rather than one
veneer that could branch indirectly to N destinations (that probably
don't have landing pads), could we instead have N veneers that branch
directly to 1 location each? Are the veneers larger than just a
branch? Is the destination unknown when the veneers are created? This
would retain the landing pad elision optimization for .text (which is
likely run more frequently than .init.text), and you could probably
put those veneers in .init.text and throw them away with the rest of
__init.
The current veneer code emits veneers close to the call site, so that the
veneer is in range for the caller.
These BTI veneers need to be emitted at the target end, so that the real
target is withing direct branching range of the veneer.
The PLT veneers are 12 bytes (ADRP + ADD + BR). These BTI veneers will
need to be BTI_C + B, so 8 bytes.
I'm prototyping something atm that may be able to address the .init.text
vs .text issue. Fixing livepatch is a taller order.
TBH I'd missed that that got closed, basically it's what's in the report
there - the GCC people really dislike the idea of adding landing pads
and want to see veneers added by the linker to fix up issues where
they're missing.
At the least, I could imagine there being a `-fno-omit-bti-pads` or
whatever for the kernel to opt into this behavior.