/* * sys_iopl has to be used when you want to access the IO ports * beyond the 0x3ff range: to get the full 65536 ports bitmapped * you'd need 8kB of bitmaps/process, which is a bit excessive. * * Here we just change the flags value on the stack: we allow * only the super-user to do it. This depends on the stack-layout * on system-call entry - see also fork() and the signal handling * code. */ static int do_iopl(unsigned int level, struct pt_regs *regs) { unsigned int old = (regs->flags >> 12) & 3; if (level > 3) return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { #ifdef CONFIG_GRKERNSEC_IO gr_handle_iopl(); return -EPERM; #else if (!capable(CAP_SYS_RAWIO)) return -EPERM; #endif } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); return 0; }
/* * sys_iopl has to be used when you want to access the IO ports * beyond the 0x3ff range: to get the full 65536 ports bitmapped * you'd need 8kB of bitmaps/process, which is a bit excessive. * * Here we just change the flags value on the stack: we allow * only the super-user to do it. This depends on the stack-layout * on system-call entry - see also fork() and the signal handling * code. */ long sys_iopl(unsigned int level, struct pt_regs *regs) { unsigned int old = (regs->flags >> 12) & 3; struct thread_struct *t = ¤t->thread; if (level > 3) return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { #ifdef CONFIG_GRKERNSEC_IO if (grsec_disable_privio) { gr_handle_iopl(); return -EPERM; } #endif if (!capable(CAP_SYS_RAWIO)) return -EPERM; } regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); t->iopl = level << 12; set_iopl_mask(t->iopl); return 0; }