hw: map kernel text segment read-only

Fix #2592
This commit is contained in:
Stefan Kalkowski 2017-11-10 14:44:42 +01:00 committed by Christian Helmuth
parent 3cdcb528ff
commit 323de9b229
9 changed files with 88 additions and 107 deletions

View File

@ -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);

View File

@ -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) **

View File

@ -16,11 +16,8 @@
#include <kernel/thread.h>
#include <kernel/pd.h>
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));
}

View File

@ -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_ */

View File

@ -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

View File

@ -20,7 +20,7 @@
void Kernel::Cpu::init(Pic &pic)
{
Cpu::Gdt::init();
gdt.init((addr_t)&tss);
Idt::init();
Tss::init();

View File

@ -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"

View File

@ -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"

View File

@ -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