diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-03-16 14:14:22 -0700 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2016-05-01 00:05:19 +0200 |
commit | 64731eb996c201464143d6ee701c3ff2e95c1a2c (patch) | |
tree | 105244b83c70288e4f90114a094e42370a51ee18 /arch/x86 | |
parent | 880ee9d2f52a511bb603ef79030d6fbd30c5d878 (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.c | 7 |
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 = ¤t->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? */ |