| From b7a584598aea7ca73140cb87b40319944dd3393f Mon Sep 17 00:00:00 2001 |
| From: Andy Lutomirski <luto@kernel.org> |
| Date: Wed, 16 Mar 2016 14:14:21 -0700 |
| Subject: x86/iopl/64: Properly context-switch IOPL on Xen PV |
| |
| commit b7a584598aea7ca73140cb87b40319944dd3393f upstream. |
| |
| 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> |
| Link: http://lkml.kernel.org/r/693c3bd7aeb4d3c27c92c622b7d0f554a458173c.1458162709.git.luto@kernel.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| [ kamal: backport to 3.19-stable: no X86_FEATURE_XENPV so just call |
| xen_pv_domain() directly ] |
| Acked-by: Andy Lutomirski <luto <at> kernel.org> |
| Signed-off-by: Kamal Mostafa <kamal <at> canonical.com> |
| Signed-off-by: Zefan Li <lizefan@huawei.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(-) |
| |
| --- a/arch/x86/include/asm/xen/hypervisor.h |
| +++ b/arch/x86/include/asm/xen/hypervisor.h |
| @@ -72,4 +72,6 @@ static inline bool xen_x2apic_para_avail |
| } |
| #endif |
| |
| +extern void xen_set_iopl_mask(unsigned mask); |
| + |
| #endif /* _ASM_X86_XEN_HYPERVISOR_H */ |
| --- a/arch/x86/kernel/process_64.c |
| +++ b/arch/x86/kernel/process_64.c |
| @@ -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, |
| 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 |
| + |
| return prev_p; |
| } |
| |
| --- a/arch/x86/xen/enlighten.c |
| +++ b/arch/x86/xen/enlighten.c |
| @@ -860,7 +860,7 @@ static void xen_load_sp0(struct tss_stru |
| xen_mc_issue(PARAVIRT_LAZY_CPU); |
| } |
| |
| -static void xen_set_iopl_mask(unsigned mask) |
| +void xen_set_iopl_mask(unsigned mask) |
| { |
| struct physdev_set_iopl set_iopl; |
| |