aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-03-16 17:14:22 -0400
committerIngo Molnar <mingo@kernel.org>2016-03-17 04:49:27 -0400
commitc29016cf41fe9fa994a5ecca607cf5f1cd98801e (patch)
treefd6fd91de61bc2e7b407cf13cf2ff07aba334e4a
parentb7a584598aea7ca73140cb87b40319944dd3393f (diff)
x86/iopl: Fix iopl capability check on Xen PV
iopl(3) is supposed to work if iopl is already 3, even if unprivileged. This didn't work right on Xen PV. Fix it. 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/8ce12013e6e4c0a44a97e316be4a6faff31bd5ea.1458162709.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/ioport.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 37dae792dbbe..589b3193f102 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -96,9 +96,14 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
96SYSCALL_DEFINE1(iopl, unsigned int, level) 96SYSCALL_DEFINE1(iopl, unsigned int, level)
97{ 97{
98 struct pt_regs *regs = current_pt_regs(); 98 struct pt_regs *regs = current_pt_regs();
99 unsigned int old = (regs->flags >> 12) & 3;
100 struct thread_struct *t = &current->thread; 99 struct thread_struct *t = &current->thread;
101 100
101 /*
102 * Careful: the IOPL bits in regs->flags are undefined under Xen PV
103 * and changing them has no effect.
104 */
105 unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT;
106
102 if (level > 3) 107 if (level > 3)
103 return -EINVAL; 108 return -EINVAL;
104 /* Trying to gain more privileges? */ 109 /* Trying to gain more privileges? */
@@ -106,8 +111,9 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
106 if (!capable(CAP_SYS_RAWIO)) 111 if (!capable(CAP_SYS_RAWIO))
107 return -EPERM; 112 return -EPERM;
108 } 113 }
109 regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); 114 regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
110 t->iopl = level << 12; 115 (level << X86_EFLAGS_IOPL_BIT);
116 t->iopl = level << X86_EFLAGS_IOPL_BIT;
111 set_iopl_mask(t->iopl); 117 set_iopl_mask(t->iopl);
112 118
113 return 0; 119 return 0;