summaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/ioport.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/ioport.c')
-rw-r--r--arch/i386/kernel/ioport.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index 2e3beb11b..445a26613 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -58,7 +58,7 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
+ if (turn_on && !capable(CAP_SYS_RAWIO))
return -EPERM;
/*
* If it's the first ioperm() call in this thread's lifetime, set the
@@ -91,11 +91,15 @@ asmlinkage int sys_iopl(unsigned long unused)
{
struct pt_regs * regs = (struct pt_regs *) &unused;
unsigned int level = regs->ebx;
+ unsigned int old = (regs->eflags >> 12) & 3;
if (level > 3)
return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
+ /* Trying to gain more privileges? */
+ if (level > old) {
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ }
regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
return 0;
}