]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/iopl/64: properly context-switch IOPL on Xen PV
authorAndy Lutomirski <luto@kernel.org>
Wed, 23 Mar 2016 10:38:23 +0000 (03:38 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 23 Mar 2016 10:38:23 +0000 (03:38 -0700)
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>
Orabug: 22926124
Conflicts:
  arch/x86/kernel/process_64.c
  X86_FEATURE_XENPV not defined, too much extra to bring it in.
  Replaced with xen_pv_domain() which is trigger to set X86_FEATURE_XENPV.
CVE: CVE-2016-3157
Signed-off-by: Chuck Anderson <chuck.anderson@oracle.com>
arch/x86/include/asm/xen/hypervisor.h
arch/x86/kernel/process_64.c
arch/x86/xen/enlighten.c

index d866959e5685a49dd3c455bdb7610ff5d83df544..daa7779beb4de48d8addeabc1b9bc9794cf9afd1 100644 (file)
@@ -57,4 +57,6 @@ static inline bool xen_x2apic_para_available(void)
 }
 #endif
 
+void xen_set_iopl_mask(unsigned mask);
+
 #endif /* _ASM_X86_XEN_HYPERVISOR_H */
index ddfdbf74f1744c235fb80ee2ee0718152882b2ce..a755aa73a12c7ce85e4701d40ac63786a2092636 100644 (file)
@@ -49,6 +49,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);
 
@@ -419,6 +420,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(xen_pv_domain() &&
+                    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
index 45dcdc2f9683ba154ad9a3cb7f20d36e6f0a96b0..4507bb41d130d3272448a7ad5f031bc66ff5b9ee 100644 (file)
@@ -931,7 +931,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;