Skip to content

Commit 614c0b9

Browse files
mrutland-armwilldeacon
authored andcommitted
arm64: prevent instrumentation of bp hardening callbacks
We may call arm64_apply_bp_hardening() early during entry (e.g. in el0_ia()) before it is safe to run instrumented code. Unfortunately this may result in running instrumented code in two cases: * The hardening callbacks called by arm64_apply_bp_hardening() are not marked as `noinstr`, and have been observed to be instrumented when compiled with either GCC or LLVM. * Since arm64_apply_bp_hardening() itself is only marked as `inline` rather than `__always_inline`, it is possible that the compiler decides to place it out-of-line, whereupon it may be instrumented. For example, with defconfig built with clang 13.0.0, call_hvc_arch_workaround_1() is compiled as: | <call_hvc_arch_workaround_1>: | d503233f paciasp | f81f0ffe str x30, [sp, #-16]! | 320183e0 mov w0, #0x80008000 | d503201f nop | d4000002 hvc #0x0 | f84107fe ldr x30, [sp], #16 | d50323bf autiasp | d65f03c0 ret ... but when CONFIG_FTRACE=y and CONFIG_KCOV=y this is compiled as: | <call_hvc_arch_workaround_1>: | d503245f bti c | d503201f nop | d503201f nop | d503233f paciasp | a9bf7bfd stp x29, x30, [sp, #-16]! | 910003fd mov x29, sp | 94000000 bl 0 <__sanitizer_cov_trace_pc> | 320183e0 mov w0, #0x80008000 | d503201f nop | d4000002 hvc #0x0 | a8c17bfd ldp x29, x30, [sp], #16 | d50323bf autiasp | d65f03c0 ret ... with a patchable function entry registered with ftrace, and a direct call to __sanitizer_cov_trace_pc(). Neither of these are safe early during entry sequences. This patch avoids the unsafe instrumentation by marking arm64_apply_bp_hardening() as `__always_inline` and by marking the hardening functions as `noinstr`. This avoids the potential for instrumentation, and causes clang to consistently generate the function as with the defconfig sample. Note: in the defconfig compilation, when CONFIG_SVE=y, x30 is spilled to the stack without being placed in a frame record, which will result in a missing entry if call_hvc_arch_workaround_1() is backtraced. Similar is true of qcom_link_stack_sanitisation(), where inline asm spills the LR to a GPR prior to corrupting it. This is not a significant issue presently as we will only backtrace here if an exception is taken, and in such cases we may omit entries for other reasons today. The relevant hardening functions were introduced in commits: ec82b56 ("arm64: Implement branch predictor hardening for Falkor") b092201 ("arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support") ... and these were subsequently moved in commit: d4647f0 ("arm64: Rewrite Spectre-v2 mitigation code") The arm64_apply_bp_hardening() function was introduced in commit: 0f15adb ("arm64: Add skeleton to harden the branch predictor against aliasing attacks") ... and was subsequently moved and reworked in commit: 6279017 ("KVM: arm64: Move BP hardening helpers into spectre.h") Fixes: ec82b56 ("arm64: Implement branch predictor hardening for Falkor") Fixes: b092201 ("arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support") Fixes: d4647f0 ("arm64: Rewrite Spectre-v2 mitigation code") Fixes: 0f15adb ("arm64: Add skeleton to harden the branch predictor against aliasing attacks") Fixes: 6279017 ("KVM: arm64: Move BP hardening helpers into spectre.h") Signed-off-by: Mark Rutland <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: James Morse <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Mark Brown <[email protected]> Cc: Will Deacon <[email protected]> Acked-by: Marc Zyngier <[email protected]> Reviewed-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 032e6c3 commit 614c0b9

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

arch/arm64/include/asm/spectre.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ struct bp_hardening_data {
6767

6868
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
6969

70-
static inline void arm64_apply_bp_hardening(void)
70+
/* Called during entry so must be __always_inline */
71+
static __always_inline void arm64_apply_bp_hardening(void)
7172
{
7273
struct bp_hardening_data *d;
7374

arch/arm64/kernel/proton-pack.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,17 +193,20 @@ static void install_bp_hardening_cb(bp_hardening_cb_t fn)
193193
__this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
194194
}
195195

196-
static void call_smc_arch_workaround_1(void)
196+
/* Called during entry so must be noinstr */
197+
static noinstr void call_smc_arch_workaround_1(void)
197198
{
198199
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
199200
}
200201

201-
static void call_hvc_arch_workaround_1(void)
202+
/* Called during entry so must be noinstr */
203+
static noinstr void call_hvc_arch_workaround_1(void)
202204
{
203205
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
204206
}
205207

206-
static void qcom_link_stack_sanitisation(void)
208+
/* Called during entry so must be noinstr */
209+
static noinstr void qcom_link_stack_sanitisation(void)
207210
{
208211
u64 tmp;
209212

0 commit comments

Comments
 (0)