mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 07:31:29 +00:00
x86/ibt: Disable IBT around firmware
Assume firmware isn't IBT clean and disable it across calls. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Kees Cook <keescook@chromium.org> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Link: https://lore.kernel.org/r/20220308154318.759989383@infradead.org
This commit is contained in:
parent
99c95c5d4f
commit
fe379fa4d1
@ -7,6 +7,7 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/ibt.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pgtable.h>
|
||||
@ -120,8 +121,12 @@ extern asmlinkage u64 __efi_call(void *fp, ...);
|
||||
efi_enter_mm(); \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt(p, f, args...) \
|
||||
efi_call((void *)p->f, args) \
|
||||
#define arch_efi_call_virt(p, f, args...) ({ \
|
||||
u64 ret, ibt = ibt_save(); \
|
||||
ret = efi_call((void *)p->f, args); \
|
||||
ibt_restore(ibt); \
|
||||
ret; \
|
||||
})
|
||||
|
||||
#define arch_efi_call_virt_teardown() \
|
||||
({ \
|
||||
|
@ -52,6 +52,9 @@ static inline bool is_endbr(u32 val)
|
||||
return val == gen_endbr();
|
||||
}
|
||||
|
||||
extern __noendbr u64 ibt_save(void);
|
||||
extern __noendbr void ibt_restore(u64 save);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
@ -74,6 +77,9 @@ static inline bool is_endbr(u32 val)
|
||||
|
||||
static inline bool is_endbr(u32 val) { return false; }
|
||||
|
||||
static inline u64 ibt_save(void) { return 0; }
|
||||
static inline void ibt_restore(u64 save) { }
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define ENDBR
|
||||
|
@ -232,6 +232,7 @@
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/ibt.h>
|
||||
|
||||
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
|
||||
extern int (*console_blank_hook)(int);
|
||||
@ -598,6 +599,7 @@ static long __apm_bios_call(void *_call)
|
||||
struct desc_struct save_desc_40;
|
||||
struct desc_struct *gdt;
|
||||
struct apm_bios_call *call = _call;
|
||||
u64 ibt;
|
||||
|
||||
cpu = get_cpu();
|
||||
BUG_ON(cpu != 0);
|
||||
@ -607,11 +609,13 @@ static long __apm_bios_call(void *_call)
|
||||
|
||||
apm_irq_save(flags);
|
||||
firmware_restrict_branch_speculation_start();
|
||||
ibt = ibt_save();
|
||||
APM_DO_SAVE_SEGS;
|
||||
apm_bios_call_asm(call->func, call->ebx, call->ecx,
|
||||
&call->eax, &call->ebx, &call->ecx, &call->edx,
|
||||
&call->esi);
|
||||
APM_DO_RESTORE_SEGS;
|
||||
ibt_restore(ibt);
|
||||
firmware_restrict_branch_speculation_end();
|
||||
apm_irq_restore(flags);
|
||||
gdt[0x40 / 8] = save_desc_40;
|
||||
@ -676,6 +680,7 @@ static long __apm_bios_call_simple(void *_call)
|
||||
struct desc_struct save_desc_40;
|
||||
struct desc_struct *gdt;
|
||||
struct apm_bios_call *call = _call;
|
||||
u64 ibt;
|
||||
|
||||
cpu = get_cpu();
|
||||
BUG_ON(cpu != 0);
|
||||
@ -685,10 +690,12 @@ static long __apm_bios_call_simple(void *_call)
|
||||
|
||||
apm_irq_save(flags);
|
||||
firmware_restrict_branch_speculation_start();
|
||||
ibt = ibt_save();
|
||||
APM_DO_SAVE_SEGS;
|
||||
error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
|
||||
&call->eax);
|
||||
APM_DO_RESTORE_SEGS;
|
||||
ibt_restore(ibt);
|
||||
firmware_restrict_branch_speculation_end();
|
||||
apm_irq_restore(flags);
|
||||
gdt[0x40 / 8] = save_desc_40;
|
||||
|
@ -517,6 +517,34 @@ static __init int setup_disable_pku(char *arg)
|
||||
__setup("nopku", setup_disable_pku);
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
#ifdef CONFIG_X86_KERNEL_IBT
|
||||
|
||||
__noendbr u64 ibt_save(void)
|
||||
{
|
||||
u64 msr = 0;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_IBT)) {
|
||||
rdmsrl(MSR_IA32_S_CET, msr);
|
||||
wrmsrl(MSR_IA32_S_CET, msr & ~CET_ENDBR_EN);
|
||||
}
|
||||
|
||||
return msr;
|
||||
}
|
||||
|
||||
__noendbr void ibt_restore(u64 save)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_IBT)) {
|
||||
rdmsrl(MSR_IA32_S_CET, msr);
|
||||
msr &= ~CET_ENDBR_EN;
|
||||
msr |= (save & CET_ENDBR_EN);
|
||||
wrmsrl(MSR_IA32_S_CET, msr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static __always_inline void setup_cet(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 msr = CET_ENDBR_EN;
|
||||
|
Loading…
Reference in New Issue
Block a user