Fwd: ioperm is preserved across fork and execve, but iopl is not

From: Alex Henrie
Date: Mon May 11 2015 - 16:49:46 EST


Dear kernel developers,

The ioperm and iopl calls are both used to grant a process permission
to access I/O devices directly. iopl(3) is equivalent to ioperm(0,
0xFFFF, 1). However, permissions granted through ioperm are preserved
across fork and execve, and permissions granted through iopl are not.
This makes no sense: The two calls do the same thing, so there is no
security benefit to dropping one on fork or execve but not the other.

As recently as October 2012, 32-bit Linux kernels preserved both iopl
and ioperm across fork and execve, but the behavior of iopl changed
with this commit:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/x86/kernel/process_32.c?id=6783eaa2e1253fbcbe2c2f6bb4c843abf1343caf

And the man page for iopl continues to state "permissions are
inherited by fork and execve": http://linux.die.net/man/2/iopl

A test program demonstrating the problem is attached, and I will send
a proposed patch shortly. CAP_SYS_RAWIO is still required to use
ioperm or iopl.

Please CC me on any reply, as I am not subscribed to the LKML.

-Alex
#include <stdio.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
if (iopl(3) == -1)
{
perror("iopl");
return 1;
}

if (execvp(argv[1], &argv[1]) == -1)
{
perror("execvp");
return 1;
}

return 0;
}
//Plays a tone on the system speaker for 1 second

#include <stdio.h>

int main()
{
__asm__("movb $0xB6, %al\n"
"outb %al, $0x43\n"
"inb $0x61, %al\n"
"orb $0x03, %al\n"
"outb %al, $0x61\n"
"movb $0x64, %al\n"
"outb %al, $0x42\n"
"movb $0x01, %al\n"
"outb %al, $0x42\n");
sleep(1);
__asm__("inb $0x61, %al\n"
"andb $0xFC, %al\n"
"outb %al, $0x61\n");
return 0;
}

Attachment: test.sh
Description: Bourne shell script