tss: block userspace access to all I/O ports.

A userspace process (CPL=3) can access an i/o port if the bit corresponding to
the port is set to 0 in the I/O permission bitmap.

Configure the I/O permission bitmap address beyond the last valid byte in the
TSS so access to all i/o ports is blocked.

Signed-off-by: Liu Hua <sdu.liu@huawei.com>
Change-Id: I3df76980c3735491db768f7210e71703f86bb989
PiperOrigin-RevId: 257336518
This commit is contained in:
Liu Hua 2019-07-09 22:20:45 -07:00 committed by gVisor bot
parent 7965b1272b
commit 7581e84cb6
2 changed files with 42 additions and 0 deletions

View File

@ -70,6 +70,14 @@ func (c *CPU) init() {
c.tss.ist1Lo = uint32(stackAddr)
c.tss.ist1Hi = uint32(stackAddr >> 32)
// Set the I/O bitmap base address beyond the last byte in the TSS
// to block access to the entire I/O address range.
//
// From section 18.5.2 "I/O Permission Bit Map" from Intel SDM vol1:
// I/O addresses not spanned by the map are treated as if they had set
// bits in the map.
c.tss.ioPerm = tssLimit + 1
// Permanently set the kernel segments.
c.registers.Cs = uint64(Kcode)
c.registers.Ds = uint64(Kdata)

View File

@ -56,6 +56,26 @@ void inline Int3Normal() { asm(".byte 0xcd, 0x03\r\n"); }
void inline Int3Compact() { asm(".byte 0xcc\r\n"); }
void InIOHelper(int width, int value) {
EXPECT_EXIT(
{
switch (width) {
case 1:
asm volatile("inb %%dx, %%al" ::"d"(value) : "%eax");
break;
case 2:
asm volatile("inw %%dx, %%ax" ::"d"(value) : "%eax");
break;
case 4:
asm volatile("inl %%dx, %%eax" ::"d"(value) : "%eax");
break;
default:
FAIL() << "invalid input width, only 1, 2 or 4 is allowed";
}
},
::testing::KilledBySignal(SIGSEGV), "");
}
TEST(ExceptionTest, Halt) {
// In order to prevent the regular handler from messing with things (and
// perhaps refaulting until some other signal occurs), we reset the handler to
@ -87,6 +107,20 @@ TEST(ExceptionTest, DivideByZero) {
::testing::KilledBySignal(SIGFPE), "");
}
TEST(ExceptionTest, IOAccessFault) {
// See above.
struct sigaction sa = {};
sa.sa_handler = SIG_DFL;
auto const cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGSEGV, sa));
InIOHelper(1, 0x0);
InIOHelper(2, 0x7);
InIOHelper(4, 0x6);
InIOHelper(1, 0xffff);
InIOHelper(2, 0xffff);
InIOHelper(4, 0xfffd);
}
TEST(ExceptionTest, Alignment) {
SetAlignmentCheck();
ClearAlignmentCheck();