diff options
Diffstat (limited to 'arch/i386/kernel/ioport.c')
-rw-r--r-- | arch/i386/kernel/ioport.c | 10 |
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; } |