From 323de9b2292753016db47faef0d4145ad85a5e98 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Fri, 10 Nov 2017 14:44:42 +0100 Subject: [PATCH] hw: map kernel text segment read-only Fix #2592 --- repos/base-hw/src/bootstrap/platform.cc | 4 +- .../base-hw/src/bootstrap/spec/x86_64/crt0.s | 48 ++++++++++++++- repos/base-hw/src/core/spec/x86_64/cpu.cc | 23 ++++---- repos/base-hw/src/core/spec/x86_64/cpu.h | 25 +++++++- .../src/core/spec/x86_64/exception_vector.s | 22 +------ .../src/core/spec/x86_64/kernel/cpu.cc | 2 +- .../src/core/spec/x86_64/kernel/thread.cc | 5 -- .../src/core/spec/x86_64/muen/kernel/vm.cc | 7 +-- repos/base-hw/src/lib/hw/spec/x86_64/gdt.s | 59 ------------------- 9 files changed, 88 insertions(+), 107 deletions(-) delete mode 100644 repos/base-hw/src/lib/hw/spec/x86_64/gdt.s diff --git a/repos/base-hw/src/bootstrap/platform.cc b/repos/base-hw/src/bootstrap/platform.cc index ecca3f2b06..ed05228dcc 100644 --- a/repos/base-hw/src/bootstrap/platform.cc +++ b/repos/base-hw/src/bootstrap/platform.cc @@ -120,8 +120,8 @@ Mapping Platform::_load_elf() phys = dst; } - //FIXME: set read-only accordingly - Page_flags flags{RW, segment.flags().x ? EXEC : NO_EXEC, + Page_flags flags{segment.flags().w ? RW : RO, + segment.flags().x ? EXEC : NO_EXEC, KERN, GLOBAL, RAM, CACHED}; Mapping m((addr_t)phys, (addr_t)segment.start(), size, flags); diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s index bb2eafc3ad..ae7be6c214 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s @@ -14,8 +14,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "hw/spec/x86_64/gdt.s" - .section ".text.crt0" /* magic multi-boot 1 header */ @@ -120,7 +118,51 @@ /* catch erroneous return of the kernel initialization */ 1: jmp 1b - _define_gdt 0 + + /****************************************** + ** Global Descriptor Table (GDT) ** + ** See Intel SDM Vol. 3A, section 3.5.1 ** + ******************************************/ + + .align 4 + .space 2 + __gdt_ptr: + .word 55 /* limit */ + .long 0 /* base address */ + + .set TSS_LIMIT, 0x68 + .set TSS_TYPE, 0x8900 + + .align 8 + .global __gdt_start + __gdt_start: + /* Null descriptor */ + .quad 0 + /* 64-bit code segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ + .long 0x209800 + /* 64-bit data segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ + .long 0x209300 + /* 64-bit user code segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ + .long 0x20f800 + /* 64-bit user data segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ + .long 0x20f300 + /* Task segment descriptor */ + .long TSS_LIMIT + /* GDTE_PRESENT | GDTE_SYS_TSS */ + .long TSS_TYPE + .long 0 + .long 0 + .global __gdt_end + __gdt_end: + /********************************* ** .bss (non-initialized data) ** diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.cc b/repos/base-hw/src/core/spec/x86_64/cpu.cc index 0d13448324..21708766de 100644 --- a/repos/base-hw/src/core/spec/x86_64/cpu.cc +++ b/repos/base-hw/src/core/spec/x86_64/cpu.cc @@ -16,11 +16,8 @@ #include #include -extern int __tss; extern int __idt; -extern int __gdt_start; -extern int __gdt_end; - +extern int __idt_end; Genode::Cpu::Context::Context(bool core) { @@ -44,18 +41,24 @@ void Genode::Cpu::Tss::init() void Genode::Cpu::Idt::init() { Pseudo_descriptor descriptor { - (uint16_t)((addr_t)&__tss - (addr_t)&__idt), + (uint16_t)((addr_t)&__idt_end - (addr_t)&__idt), (uint64_t)(&__idt) }; asm volatile ("lidt %0" : : "m" (descriptor)); } -void Genode::Cpu::Gdt::init() +void Genode::Cpu::Gdt::init(addr_t tss_addr) { - addr_t const start = (addr_t)&__gdt_start; - uint16_t const limit = __gdt_end - __gdt_start - 1; - uint64_t const base = start; - asm volatile ("lgdt %0" :: "m" (Pseudo_descriptor(limit, base))); + tss_desc[0] = ((((tss_addr >> 24) & 0xff) << 24 | + ((tss_addr >> 16) & 0xff) | + 0x8900) << 32) | + ((tss_addr & 0xffff) << 16 | 0x68); + tss_desc[1] = tss_addr >> 32; + + Pseudo_descriptor descriptor { + (uint16_t)(sizeof(Gdt)), + (uint64_t)(this) }; + asm volatile ("lgdt %0" :: "m" (descriptor)); } diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.h b/repos/base-hw/src/core/spec/x86_64/cpu.h index 961374f1c3..f28bfbca4f 100644 --- a/repos/base-hw/src/core/spec/x86_64/cpu.h +++ b/repos/base-hw/src/core/spec/x86_64/cpu.h @@ -56,7 +56,16 @@ class Genode::Cpu * * See Intel SDM Vol. 3A, section 7.7 */ - struct Tss { static void init(); }; + struct alignas(8) Tss + { + uint32_t reserved0; + uint64_t rsp[3]; /* pl0-3 stack pointer */ + uint64_t reserved1; + uint64_t ist[7]; /* irq stack pointer */ + uint64_t reserved2; + + static void init(); + } __attribute__((packed)) tss; /** @@ -71,7 +80,17 @@ class Genode::Cpu * Global Descriptor Table (GDT) * See Intel SDM Vol. 3A, section 3.5.1 */ - struct Gdt { static void init(); }; + struct alignas(8) Gdt + { + uint64_t null_desc = 0; + uint64_t sys_cs_64bit_desc = 0x20980000000000; + uint64_t sys_ds_64bit_desc = 0x20930000000000; + uint64_t usr_cs_64bit_desc = 0x20f80000000000; + uint64_t usr_ds_64bit_desc = 0x20f30000000000; + uint64_t tss_desc[2]; + + void init(addr_t tss_addr); + } __attribute__((packed)) gdt; /** @@ -263,6 +282,8 @@ void Genode::Cpu::switch_to(Context & context, Mmu_context & mmu_context) if ((context.cs != 0x8) && (mmu_context.cr3 != Cr3::read())) Cr3::write(mmu_context.cr3); + + tss.ist[0] = (addr_t)&context + sizeof(Genode::Cpu_state); }; #endif /* _CORE__SPEC__X86_64__CPU_H_ */ diff --git a/repos/base-hw/src/core/spec/x86_64/exception_vector.s b/repos/base-hw/src/core/spec/x86_64/exception_vector.s index 747a88c916..ca9425ee5d 100644 --- a/repos/base-hw/src/core/spec/x86_64/exception_vector.s +++ b/repos/base-hw/src/core/spec/x86_64/exception_vector.s @@ -14,19 +14,12 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "hw/spec/x86_64/gdt.s" - /* offsets of member variables in a CPU context */ .set IP_OFFSET, 17 * 8 .set SP_OFFSET, 20 * 8 -/* tss segment constants */ -.set TSS_LIMIT, 0x68 -.set TSS_TYPE, 0x8900 - /* virtual addresses */ .set BASE, 0xffffffc000000000 -.set TSS, BASE + (__tss - _begin) .set ISR, BASE .set ISR_ENTRY_SIZE, 12 @@ -153,20 +146,9 @@ .set isr_addr, isr_addr + ISR_ENTRY_SIZE .endr - /**************************************** - ** Task State Segment (TSS) ** - ** See Intel SDM Vol. 3A, section 7.7 ** - ****************************************/ - - .global __tss + .global __idt_end .align 8 - __tss: - .space 36 - .global __tss_client_context_ptr - __tss_client_context_ptr: - .space 64 - - _define_gdt TSS + __idt_end: .section .text diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc index d6fe35e3e4..d657e2a489 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/cpu.cc @@ -20,7 +20,7 @@ void Kernel::Cpu::init(Pic &pic) { - Cpu::Gdt::init(); + gdt.init((addr_t)&tss); Idt::init(); Tss::init(); diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc index 5f69a79ebb..fefa2090c2 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/thread.cc @@ -30,13 +30,8 @@ void Kernel::Thread::_call_update_pd() { } -extern void * __tss_client_context_ptr; - void Kernel::Thread::proceed(Cpu & cpu) { - void * * tss_stack_ptr = (&__tss_client_context_ptr); - *tss_stack_ptr = (void*)((addr_t)&*regs + sizeof(Genode::Cpu_state)); - cpu.switch_to(*regs, pd()->mmu_regs); asm volatile("mov %0, %%rsp \n" diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc index c9adafea38..c9e21ea170 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc @@ -56,12 +56,9 @@ void Kernel::Vm::exception(Cpu & cpu) } -extern void * __tss_client_context_ptr; - -void Kernel::Vm::proceed(Cpu &) +void Kernel::Vm::proceed(Cpu & cpu) { - void * * tss_stack_ptr = (&__tss_client_context_ptr); - *tss_stack_ptr = (void*)((addr_t)_state + sizeof(Genode::Cpu_state)); + cpu.tss.ist[0] = (addr_t)_state + sizeof(Genode::Cpu_state); asm volatile("sti \n" "mov $1, %rax \n" diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s b/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s deleted file mode 100644 index 6821f4c933..0000000000 --- a/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s +++ /dev/null @@ -1,59 +0,0 @@ -/* - * \brief GDT macro - * \author Martin Stein - * \author Stefan Kalkowski - * \date 2017-04-17 - */ - -/* - * Copyright (C) 2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/****************************************** - ** Global Descriptor Table (GDT) ** - ** See Intel SDM Vol. 3A, section 3.5.1 ** - ******************************************/ - -.macro _define_gdt tss_address - .align 4 - .space 2 - __gdt_ptr: - .word 55 /* limit */ - .long 0 /* base address */ - - .set TSS_LIMIT, 0x68 - .set TSS_TYPE, 0x8900 - - .align 8 - .global __gdt_start - __gdt_start: - /* Null descriptor */ - .quad 0 - /* 64-bit code segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ - .long 0x209800 - /* 64-bit data segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ - .long 0x209300 - /* 64-bit user code segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ - .long 0x20f800 - /* 64-bit user data segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ - .long 0x20f300 - /* Task segment descriptor */ - .long (\tss_address & 0xffff) << 16 | TSS_LIMIT - /* GDTE_PRESENT | GDTE_SYS_TSS */ - .long ((\tss_address >> 24) & 0xff) << 24 | ((\tss_address >> 16) & 0xff) | TSS_TYPE - .long \tss_address >> 32 - .long 0 - .global __gdt_end - __gdt_end: -.endm