mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 09:59:32 +00:00
arm64: prevent instrumentation of bp hardening callbacks
[ Upstream commit614c0b9fee
] 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:ec82b567a7
("arm64: Implement branch predictor hardening for Falkor")b092201e00
("arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support") ... and these were subsequently moved in commit:d4647f0a2a
("arm64: Rewrite Spectre-v2 mitigation code") The arm64_apply_bp_hardening() function was introduced in commit:0f15adbb28
("arm64: Add skeleton to harden the branch predictor against aliasing attacks") ... and was subsequently moved and reworked in commit:6279017e80
("KVM: arm64: Move BP hardening helpers into spectre.h") Fixes:ec82b567a7
("arm64: Implement branch predictor hardening for Falkor") Fixes:b092201e00
("arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support") Fixes:d4647f0a2a
("arm64: Rewrite Spectre-v2 mitigation code") Fixes:0f15adbb28
("arm64: Add skeleton to harden the branch predictor against aliasing attacks") Fixes:6279017e80
("KVM: arm64: Move BP hardening helpers into spectre.h") Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: James Morse <james.morse@arm.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Mark Brown <broonie@kernel.org> Cc: Will Deacon <will@kernel.org> Acked-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20220224181028.512873-1-mark.rutland@arm.com Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
df04ef6334
commit
d362998e8d
2 changed files with 8 additions and 4 deletions
|
@ -67,7 +67,8 @@ struct bp_hardening_data {
|
||||||
|
|
||||||
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
|
DECLARE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data);
|
||||||
|
|
||||||
static inline void arm64_apply_bp_hardening(void)
|
/* Called during entry so must be __always_inline */
|
||||||
|
static __always_inline void arm64_apply_bp_hardening(void)
|
||||||
{
|
{
|
||||||
struct bp_hardening_data *d;
|
struct bp_hardening_data *d;
|
||||||
|
|
||||||
|
|
|
@ -233,17 +233,20 @@ static void install_bp_hardening_cb(bp_hardening_cb_t fn)
|
||||||
__this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
|
__this_cpu_write(bp_hardening_data.slot, HYP_VECTOR_SPECTRE_DIRECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void call_smc_arch_workaround_1(void)
|
/* Called during entry so must be noinstr */
|
||||||
|
static noinstr void call_smc_arch_workaround_1(void)
|
||||||
{
|
{
|
||||||
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void call_hvc_arch_workaround_1(void)
|
/* Called during entry so must be noinstr */
|
||||||
|
static noinstr void call_hvc_arch_workaround_1(void)
|
||||||
{
|
{
|
||||||
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qcom_link_stack_sanitisation(void)
|
/* Called during entry so must be noinstr */
|
||||||
|
static noinstr void qcom_link_stack_sanitisation(void)
|
||||||
{
|
{
|
||||||
u64 tmp;
|
u64 tmp;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue