84 lines
2.7 KiB
Diff
84 lines
2.7 KiB
Diff
From 91b210501e1bc7518a44d24526f223375bf3d039 Mon Sep 17 00:00:00 2001
|
|
From: Andy Lutomirski <luto@kernel.org>
|
|
Date: Thu, 17 Mar 2016 17:55:31 +0100
|
|
Origin: http://xenbits.xen.org/xsa/xsa171.patch
|
|
Subject: x86/iopl/64: properly context-switch IOPL on Xen PV
|
|
|
|
On Xen PV, regs->flags doesn't reliably reflect IOPL and the
|
|
exit-to-userspace code doesn't change IOPL. We need to context
|
|
switch it manually.
|
|
|
|
I'm doing this without going through paravirt because this is
|
|
specific to Xen PV. After the dust settles, we can merge this with
|
|
the 32-bit code, tidy up the iopl syscall implementation, and remove
|
|
the set_iopl pvop entirely.
|
|
|
|
This is XSA-171.
|
|
|
|
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
|
Cc: stable@vger.kernel.org
|
|
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
|
---
|
|
arch/x86/include/asm/xen/hypervisor.h | 2 ++
|
|
arch/x86/kernel/process_64.c | 12 ++++++++++++
|
|
arch/x86/xen/enlighten.c | 2 +-
|
|
3 files changed, 15 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
|
|
index 8b2d4be..7b87b3c 100644
|
|
--- a/arch/x86/include/asm/xen/hypervisor.h
|
|
+++ b/arch/x86/include/asm/xen/hypervisor.h
|
|
@@ -62,4 +62,6 @@ void xen_arch_register_cpu(int num);
|
|
void xen_arch_unregister_cpu(int num);
|
|
#endif
|
|
|
|
+void xen_set_iopl_mask(unsigned mask);
|
|
+
|
|
#endif /* _ASM_X86_XEN_HYPERVISOR_H */
|
|
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
|
|
index e835d26..4cbb60f 100644
|
|
--- a/arch/x86/kernel/process_64.c
|
|
+++ b/arch/x86/kernel/process_64.c
|
|
@@ -48,6 +48,7 @@
|
|
#include <asm/syscalls.h>
|
|
#include <asm/debugreg.h>
|
|
#include <asm/switch_to.h>
|
|
+#include <asm/xen/hypervisor.h>
|
|
|
|
asmlinkage extern void ret_from_fork(void);
|
|
|
|
@@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|
task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
|
|
__switch_to_xtra(prev_p, next_p, tss);
|
|
|
|
+#ifdef CONFIG_XEN
|
|
+ /*
|
|
+ * On Xen PV, IOPL bits in pt_regs->flags have no effect, and
|
|
+ * current_pt_regs()->flags may not match the current task's
|
|
+ * intended IOPL. We need to switch it manually.
|
|
+ */
|
|
+ if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
|
|
+ prev->iopl != next->iopl))
|
|
+ xen_set_iopl_mask(next->iopl);
|
|
+#endif
|
|
+
|
|
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
|
|
/*
|
|
* AMD CPUs have a misfeature: SYSRET sets the SS selector but
|
|
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
|
|
index b7de78b..beab8c7 100644
|
|
--- a/arch/x86/xen/enlighten.c
|
|
+++ b/arch/x86/xen/enlighten.c
|
|
@@ -961,7 +961,7 @@ static void xen_load_sp0(struct tss_struct *tss,
|
|
tss->x86_tss.sp0 = thread->sp0;
|
|
}
|
|
|
|
-static void xen_set_iopl_mask(unsigned mask)
|
|
+void xen_set_iopl_mask(unsigned mask)
|
|
{
|
|
struct physdev_set_iopl set_iopl;
|
|
|
|
--
|
|
2.8.0.rc3
|
|
|