summaryrefslogtreecommitdiff
path: root/arch/x86
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-03-16 14:14:22 -0700
committerBen Hutchings <ben@decadent.org.uk>2016-05-01 00:05:19 +0200
commit64731eb996c201464143d6ee701c3ff2e95c1a2c (patch)
tree105244b83c70288e4f90114a094e42370a51ee18 /arch/x86
parent880ee9d2f52a511bb603ef79030d6fbd30c5d878 (diff)
x86/iopl: Fix iopl capability check on Xen PV
commit c29016cf41fe9fa994a5ecca607cf5f1cd98801e upstream. 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> Link: http://lkml.kernel.org/r/8ce12013e6e4c0a44a97e316be4a6faff31bd5ea.1458162709.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/ioport.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 8c968974253d..6a2fa4ac5a76 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -95,9 +95,14 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
*/
long sys_iopl(unsigned int level, struct pt_regs *regs)
{
- unsigned int old = (regs->flags >> 12) & 3;
struct thread_struct *t = &current->thread;
+ /*
+ * Careful: the IOPL bits in regs->flags are undefined under Xen PV
+ * and changing them has no effect.
+ */
+ unsigned int old = t->iopl >> 12;
+
if (level > 3)
return -EINVAL;
/* Trying to gain more privileges? */