diff --git a/Cargo.toml b/Cargo.toml index 08191d48d5f7eb4b32e60e36ad58280421aef196..5ac75deda3310c0b557488e9f7c0d3605c0eb09a 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 bc4ea434ea40aebbf234e45b4dab0b2b2f0fc4d8..26da847da3dd59948800dc0f36ae9d79108521ff 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 4fa7fe45a375ab1f9fd5e334ea2f57c45a1814a7..c336dae76f4a7c4067d55cffbcabad60cde8b5d3 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 7ae1a8e2ea4db31786849dbd48121029401ddde0..ffa90a968d2940e24272c0a34008ad02f9e96099 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 0000000000000000000000000000000000000000..bee8b3d1ee5a715e4ebb2bbd85228b8cfd2c7511 --- /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 97735958c68cef615d6c40309bc996fa569974ba..ddc7b61de95b3445da574d0b2acf723afe62bc56 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 5129460769acf89e1f999a7fe7c8fb66706b4304..309c4935343601f11a821651750f942fe8fc7be9 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 d0ff5f32ec1058aaaec69c7e7960a7f67baf4c75..e65d2a2216741150c2dac38f489d0702f2e5a9e7 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<usize> { match a & SYS_CLASS { diff --git a/src/syscall/process.rs b/src/syscall/process.rs index d3f72abfb33d037957b827b15b82a1f603d3333a..1b0bb2dd117dce1061e6d59c7fc7d102197bdb5a 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -355,15 +355,24 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> { 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);