aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-03-16 17:14:21 -0400
committerIngo Molnar <mingo@kernel.org>2016-03-17 04:49:26 -0400
commitb7a584598aea7ca73140cb87b40319944dd3393f (patch)
tree79f30be94b46b3bf08eb2ab82921973fef2c0064
parentb08983015cdddca7e41c95f5054e2a8fb222a264 (diff)
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. Fixes XSA-171. Reviewewd-by: Jan Beulich <JBeulich@suse.com> Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Andrew Cooper <andrew.cooper3@citrix.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jan Beulich <JBeulich@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/693c3bd7aeb4d3c27c92c622b7d0f554a458173c.1458162709.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/xen/hypervisor.h2
-rw-r--r--arch/x86/kernel/process_64.c12
-rw-r--r--arch/x86/xen/enlighten.c2
3 files changed, 15 insertions, 1 deletions
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
index 8b2d4bea9962..39171b3646bb 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);
62void xen_arch_unregister_cpu(int num); 62void xen_arch_unregister_cpu(int num);
63#endif 63#endif
64 64
65extern void xen_set_iopl_mask(unsigned mask);
66
65#endif /* _ASM_X86_XEN_HYPERVISOR_H */ 67#endif /* _ASM_X86_XEN_HYPERVISOR_H */
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index b9d99e0f82c4..9f751876066f 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -48,6 +48,7 @@
48#include <asm/syscalls.h> 48#include <asm/syscalls.h>
49#include <asm/debugreg.h> 49#include <asm/debugreg.h>
50#include <asm/switch_to.h> 50#include <asm/switch_to.h>
51#include <asm/xen/hypervisor.h>
51 52
52asmlinkage extern void ret_from_fork(void); 53asmlinkage extern void ret_from_fork(void);
53 54
@@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
411 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) 412 task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
412 __switch_to_xtra(prev_p, next_p, tss); 413 __switch_to_xtra(prev_p, next_p, tss);
413 414
415#ifdef CONFIG_XEN
416 /*
417 * On Xen PV, IOPL bits in pt_regs->flags have no effect, and
418 * current_pt_regs()->flags may not match the current task's
419 * intended IOPL. We need to switch it manually.
420 */
421 if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
422 prev->iopl != next->iopl))
423 xen_set_iopl_mask(next->iopl);
424#endif
425
414 if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) { 426 if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
415 /* 427 /*
416 * AMD CPUs have a misfeature: SYSRET sets the SS selector but 428 * 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 2c261082eadf..8381fb990c7f 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,
961 tss->x86_tss.sp0 = thread->sp0; 961 tss->x86_tss.sp0 = thread->sp0;
962} 962}
963 963
964static void xen_set_iopl_mask(unsigned mask) 964void xen_set_iopl_mask(unsigned mask)
965{ 965{
966 struct physdev_set_iopl set_iopl; 966 struct physdev_set_iopl set_iopl;
967 967