From a6550341bbe3614d595dd8ba8113517f3a25f637 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 8 Jan 2018 22:31:50 -0700 Subject: [PATCH] Add trampolines for PTI support --- Cargo.toml | 3 ++- src/arch/x86_64/interrupt/syscall.rs | 23 +++++++++++---------- src/arch/x86_64/macros.rs | 30 ++++++++++++++++++++++++++++ src/arch/x86_64/mod.rs | 5 ++++- src/arch/x86_64/pti.rs | 25 +++++++++++++++++++++++ src/arch/x86_64/start.rs | 4 ++++ src/consts.rs | 3 ++- src/syscall/mod.rs | 7 +------ src/syscall/process.rs | 13 ++++++++++-- 9 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 src/arch/x86_64/pti.rs diff --git a/Cargo.toml b/Cargo.toml index 08191d4..5ac75de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,8 @@ version = "0.7" default-features = false [features] -default = [] +default = ["pti"] doc = [] live = [] multi_core = [] +pti = [] diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index bc4ea43..26da847 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -1,20 +1,23 @@ +use arch::x86_64::pti; +use syscall; + #[naked] pub unsafe extern fn syscall() { #[inline(never)] unsafe fn inner(stack: &mut SyscallStack) { - extern { - fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, rbp: usize, stack: &mut SyscallStack) -> usize; - } - let mut a; - { - let b; - let rbp; - asm!("" : "={rax}"(a), "={rbx}"(b), "={rbp}"(rbp) + let b; + let rbp; + asm!("" : "={rax}"(a), "={rbx}"(b), "={rbp}"(rbp) : : : "intel", "volatile"); - a = syscall(a, b, stack.rcx, stack.rdx, stack.rsi, stack.rdi, rbp, stack); - } + // Map kernel + pti::map(); + + a = syscall::syscall(a, b, stack.rcx, stack.rdx, stack.rsi, stack.rdi, rbp, stack); + + // Unmap kernel + pti::unmap(); asm!("" : : "{rax}"(a) : : "intel", "volatile"); } diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs index 4fa7fe4..c336dae 100644 --- a/src/arch/x86_64/macros.rs +++ b/src/arch/x86_64/macros.rs @@ -166,7 +166,13 @@ macro_rules! interrupt { pub unsafe extern fn $name () { #[inline(never)] unsafe fn inner() { + // Map kernel + $crate::arch::x86_64::pti::map(); + $func + + // Unmap kernel + $crate::arch::x86_64::pti::unmap(); } // Push scratch registers @@ -207,7 +213,13 @@ macro_rules! interrupt_stack { pub unsafe extern fn $name () { #[inline(never)] unsafe fn inner($stack: &mut $crate::arch::x86_64::macros::InterruptStack) { + // Map kernel + $crate::arch::x86_64::pti::map(); + $func + + // Unmap kernel + $crate::arch::x86_64::pti::unmap(); } // Push scratch registers @@ -254,7 +266,13 @@ macro_rules! interrupt_error { pub unsafe extern fn $name () { #[inline(never)] unsafe fn inner($stack: &$crate::arch::x86_64::macros::InterruptErrorStack) { + // Map kernel + $crate::arch::x86_64::pti::map(); + $func + + // Unmap kernel + $crate::arch::x86_64::pti::unmap(); } // Push scratch registers @@ -302,7 +320,13 @@ macro_rules! interrupt_stack_p { pub unsafe extern fn $name () { #[inline(never)] unsafe fn inner($stack: &mut $crate::arch::x86_64::macros::InterruptStackP) { + // Map kernel + $crate::arch::x86_64::pti::map(); + $func + + // Unmap kernel + $crate::arch::x86_64::pti::unmap(); } // Push scratch registers @@ -353,7 +377,13 @@ macro_rules! interrupt_error_p { pub unsafe extern fn $name () { #[inline(never)] unsafe fn inner($stack: &$crate::arch::x86_64::macros::InterruptErrorStackP) { + // Map kernel + $crate::arch::x86_64::pti::map(); + $func + + // Unmap kernel + $crate::arch::x86_64::pti::unmap(); } // Push scratch registers diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 7ae1a8e..ffa90a9 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -16,8 +16,11 @@ pub mod interrupt; /// Paging pub mod paging; +/// Page table isolation +pub mod pti; + /// Initialization and start function pub mod start; /// Stop function -pub mod stop; \ No newline at end of file +pub mod stop; diff --git a/src/arch/x86_64/pti.rs b/src/arch/x86_64/pti.rs new file mode 100644 index 0000000..bee8b3d --- /dev/null +++ b/src/arch/x86_64/pti.rs @@ -0,0 +1,25 @@ +#[cfg(feature = "pti")] +#[inline(always)] +pub unsafe fn map() { + let _cr3: usize; + asm!("mov $0, cr3 + mov cr3, $0" + : "=r"(_cr3) : : "memory" : "intel", "volatile"); +} + +#[cfg(feature = "pti")] +#[inline(always)] +pub unsafe fn unmap() { + let _cr3: usize; + asm!("mov $0, cr3 + mov cr3, $0" + : "=r"(_cr3) : : "memory" : "intel", "volatile"); +} + +#[cfg(not(feature = "pti"))] +#[inline(always)] +pub unsafe fn map() {} + +#[cfg(not(feature = "pti"))] +#[inline(always)] +pub unsafe fn unmap() {} diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index 9773595..ddc7b61 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -8,6 +8,7 @@ use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE use acpi; use allocator; +use arch::x86_64::pti; use device; use gdt; use idt; @@ -190,6 +191,9 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! { } pub unsafe fn usermode(ip: usize, sp: usize, arg: usize) -> ! { + // Unmap kernel + pti::unmap(); + // Go to usermode asm!("mov ds, r10d mov es, r10d diff --git a/src/consts.rs b/src/consts.rs index 5129460..309c493 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -16,7 +16,8 @@ pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE; /// Offset to kernel heap - pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET + PML4_SIZE/2; + pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE; + pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE; /// Size of kernel heap pub const KERNEL_HEAP_SIZE: usize = 256 * 1024 * 1024; // 256 MB diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index d0ff5f3..e65d2a2 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -44,12 +44,7 @@ pub mod time; /// Validate input pub mod validate; -//mod print_call; -//use self::print_call::print_call; - - -#[no_mangle] -pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> usize { +pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> usize { #[inline(always)] fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: usize, stack: &mut SyscallStack) -> Result { match a & SYS_CLASS { diff --git a/src/syscall/process.rs b/src/syscall/process.rs index d3f72ab..1b0bb2d 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -355,15 +355,24 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { context.arch.set_page_table(unsafe { new_table.address() }); - // Copy kernel mapping + // Copy kernel image mapping { - let frame = active_table.p4()[::KERNEL_PML4].pointed_frame().expect("kernel table not mapped"); + let frame = active_table.p4()[::KERNEL_PML4].pointed_frame().expect("kernel image not mapped"); let flags = active_table.p4()[::KERNEL_PML4].flags(); active_table.with(&mut new_table, &mut temporary_page, |mapper| { mapper.p4_mut()[::KERNEL_PML4].set(frame, flags); }); } + // Copy kernel heap mapping + { + let frame = active_table.p4()[::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped"); + let flags = active_table.p4()[::KERNEL_HEAP_PML4].flags(); + active_table.with(&mut new_table, &mut temporary_page, |mapper| { + mapper.p4_mut()[::KERNEL_HEAP_PML4].set(frame, flags); + }); + } + if let Some(fx) = kfx_option.take() { context.arch.set_fx(fx.as_ptr() as usize); context.kfx = Some(fx);