1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:57:45 +00:00

Kernel: Prevent executing I/O instructions in userspace

All threads were running with iomapbase=0 in their TSS, which the CPU
interprets as "there's an I/O permission bitmap starting at offset 0
into my TSS".

Because of that, any bits that were 1 inside the TSS would allow the
thread to execute I/O instructions on the port with that bit index.

Fix this by always setting the iomapbase to sizeof(TSS32), and also
setting the TSS descriptor's limit to sizeof(TSS32), effectively making
the I/O permissions bitmap zero-length.

This should make it no longer possible to do I/O from userspace. :^)
This commit is contained in:
Andreas Kling 2020-01-01 17:26:25 +01:00
parent 37329c2009
commit f598bbbb1d
5 changed files with 21 additions and 6 deletions

View file

@ -705,6 +705,8 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
new_main_thread->make_thread_specific_region({});
memset(&tss, 0, sizeof(TSS32));
tss.iomapbase = sizeof(TSS32);
tss.eflags = 0x0202;
tss.eip = entry_eip;
tss.cs = 0x1b;

View file

@ -476,10 +476,10 @@ bool Scheduler::context_switch(Thread& thread)
thread.set_selector(gdt_alloc_entry());
auto& descriptor = get_gdt_entry(thread.selector());
descriptor.set_base(&thread.tss());
descriptor.set_limit(0xffff);
descriptor.set_limit(sizeof(TSS32));
descriptor.dpl = 0;
descriptor.segment_present = 1;
descriptor.granularity = 1;
descriptor.granularity = 0;
descriptor.zero = 0;
descriptor.operation_size = 1;
descriptor.descriptor_type = 0;
@ -501,10 +501,10 @@ static void initialize_redirection()
{
auto& descriptor = get_gdt_entry(s_redirection.selector);
descriptor.set_base(&s_redirection.tss);
descriptor.set_limit(0xffff);
descriptor.set_limit(sizeof(TSS32));
descriptor.dpl = 0;
descriptor.segment_present = 1;
descriptor.granularity = 1;
descriptor.granularity = 0;
descriptor.zero = 0;
descriptor.operation_size = 1;
descriptor.descriptor_type = 0;

View file

@ -59,6 +59,7 @@ Thread::Thread(Process& process)
m_fpu_state = (FPUState*)kmalloc_aligned(sizeof(FPUState), 16);
memcpy(m_fpu_state, &s_clean_fpu_state, sizeof(FPUState));
memset(&m_tss, 0, sizeof(m_tss));
m_tss.iomapbase = sizeof(TSS32);
// Only IF is set when a process boots.
m_tss.eflags = 0x0202;