diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index c9103a6fa06e..0b0e0283994f 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -124,7 +124,8 @@ bool emulate_vsyscall(unsigned long error_code, if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER) return false; - if (!(error_code & X86_PF_INSTR)) { + /* Avoid emulation unless userspace was executing from vsyscall page: */ + if (address != regs->ip) { /* Failed vsyscall read */ if (vsyscall_mode == EMULATE) return false; @@ -136,13 +137,16 @@ bool emulate_vsyscall(unsigned long error_code, return false; } + + /* X86_PF_INSTR is only set when NX is supported: */ + if (cpu_feature_enabled(X86_FEATURE_NX)) + WARN_ON_ONCE(!(error_code & X86_PF_INSTR)); + /* * No point in checking CS -- the only way to get here is a user mode * trap to a high address, which means that we're in 64-bit user code. */ - WARN_ON_ONCE(address != regs->ip); - if (vsyscall_mode == NONE) { warn_bad_vsyscall(KERN_INFO, regs, "vsyscall attempted with vsyscall=none"); diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 39f80111e6f1..e3ce9b0b2447 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -665,6 +665,7 @@ static unsigned long mm_mangle_tif_spec_bits(struct task_struct *next) static void cond_mitigation(struct task_struct *next) { unsigned long prev_mm, next_mm; + bool userspace_needs_ibpb = false; if (!next || !next->mm) return; @@ -722,7 +723,7 @@ static void cond_mitigation(struct task_struct *next) */ if (next_mm != prev_mm && (next_mm | prev_mm) & LAST_USER_MM_IBPB) - indirect_branch_prediction_barrier(); + userspace_needs_ibpb = true; } if (static_branch_unlikely(&switch_mm_always_ibpb)) { @@ -732,9 +733,11 @@ static void cond_mitigation(struct task_struct *next) * last on this CPU. */ if ((prev_mm & ~LAST_USER_MM_SPEC_MASK) != (unsigned long)next->mm) - indirect_branch_prediction_barrier(); + userspace_needs_ibpb = true; } + this_cpu_write(x86_ibpb_exit_to_user, userspace_needs_ibpb); + if (static_branch_unlikely(&switch_mm_cond_l1d_flush)) { /* * Flush L1D when the outgoing task requested it and/or diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig index f2f538c70650..a5d66bfd9e50 100644 --- a/drivers/iommu/intel/Kconfig +++ b/drivers/iommu/intel/Kconfig @@ -48,7 +48,10 @@ config INTEL_IOMMU_DEBUGFS config INTEL_IOMMU_SVM bool "Support for Shared Virtual Memory with Intel IOMMU" - depends on X86_64 + # The kernel does not invalidate IOTLB entries when freeing + # kernel page tables. This can lead to IOMMUs walking (and + # writing to) CPU page tables after they are freed. + depends on BROKEN select MMU_NOTIFIER select IOMMU_SVA help