From 41d5a2a786726b3655b0dd444b77b76ab1aa45f3 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 6 Aug 2021 18:08:04 +0200 Subject: [PATCH] Use naked functions in syscall inst handler too. --- src/arch/x86_64/gdt.rs | 3 --- src/arch/x86_64/interrupt/handler.rs | 28 ------------------- src/arch/x86_64/interrupt/syscall.rs | 40 +++++++++++++++++++--------- 3 files changed, 27 insertions(+), 44 deletions(-) diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index 5e974c3d..b55db056 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -78,9 +78,6 @@ pub static mut GDT: [GdtEntry; 10] = [ #[repr(C, align(16))] pub struct ProcessorControlRegion { - // NOTE: If you plan to change any fields here, please make sure that you also modify the - // offsets in the syscall instruction handler accordingly! - pub tcb_end: usize, pub user_rsp_tmp: usize, pub tss: TssWrapper, diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index 58ee4dd7..4cf27e87 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -203,34 +203,6 @@ impl InterruptErrorStack { } } -#[macro_export] -macro_rules! intel_asm { - ($($strings:expr,)+) => { - global_asm!(concat!( - $($strings),+, - )); - }; -} -#[macro_export] -macro_rules! function { - ($name:ident => { $($body:expr,)+ }) => { - intel_asm!( - ".global ", stringify!($name), "\n", - ".type ", stringify!($name), ", @function\n", - ".section .text.", stringify!($name), ", \"ax\", @progbits\n", - // Align the function to a 16-byte boundary, padding with multi-byte NOPs. - ".p2align 4,,15\n", - stringify!($name), ":\n", - $($body),+, - ".size ", stringify!($name), ", . - ", stringify!($name), "\n", - ".text\n", - ); - extern "C" { - pub fn $name(); - } - }; -} - #[macro_export] macro_rules! push_scratch { () => { " diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index 3fbc49ac..38c78c23 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -5,7 +5,8 @@ use crate::{ syscall, syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL}, }; -use x86::msr; +use memoffset::offset_of; +use x86::{bits64::task::TaskStateSegment, msr, segmentation::SegmentSelector}; pub unsafe fn init() { // IA32_STAR[31:0] are reserved. @@ -58,16 +59,18 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack) }); } -function!(syscall_instruction => { +#[naked] +pub unsafe extern "C" fn syscall_instruction() { + asm!(concat!( // Yes, this is magic. No, you don't need to understand " swapgs // Set gs segment to TSS - mov gs:[0x08], rsp // Save userspace stack pointer - mov rsp, gs:[0x14] // Load kernel stack pointer - push QWORD PTR 5 * 8 + 3 // Push fake userspace SS (resembling iret frame) - push QWORD PTR gs:[0x08] // Push userspace rsp + mov gs:[{sp}], rsp // Save userspace stack pointer + mov rsp, gs:[{ksp}] // Load kernel stack pointer + push QWORD PTR {ss_sel} // Push fake userspace SS (resembling iret frame) + push QWORD PTR gs:[{sp}] // Push userspace rsp push r11 // Push rflags - push QWORD PTR 6 * 8 + 3 // Push fake CS (resembling iret stack frame) + push QWORD PTR {cs_sel} // Push fake CS (resembling iret stack frame) push rcx // Push userspace return pointer ", @@ -113,8 +116,8 @@ function!(syscall_instruction => { pop rcx // Pop userspace return pointer add rsp, 8 // Pop fake userspace CS pop r11 // Pop rflags - pop QWORD PTR gs:[0x08] // Pop userspace stack pointer - mov rsp, gs:[0x08] // Restore userspace stack pointer + pop QWORD PTR gs:[{sp}] // Pop userspace stack pointer + mov rsp, gs:[{sp}] // Restore userspace stack pointer swapgs // Restore gs from TSS to user data sysretq // Return into userspace; RCX=>RIP,R11=>RFLAGS @@ -125,8 +128,16 @@ function!(syscall_instruction => { xor r11, r11 swapgs iretq - ", -}); + "), + + sp = const(offset_of!(gdt::ProcessorControlRegion, user_rsp_tmp)), + ksp = const(offset_of!(gdt::ProcessorControlRegion, tss) + offset_of!(TaskStateSegment, rsp)), + ss_sel = const(SegmentSelector::new(gdt::GDT_USER_DATA as u16, x86::Ring::Ring3).bits()), + cs_sel = const(SegmentSelector::new(gdt::GDT_USER_CODE as u16, x86::Ring::Ring3).bits()), + + options(noreturn), + ); +} interrupt_stack!(syscall, |stack| { with_interrupt_stack!(|stack| { @@ -150,7 +161,9 @@ interrupt_stack!(syscall, |stack| { }) }); -function!(clone_ret => { +#[naked] +pub unsafe extern "C" fn clone_ret() { + asm!(concat!( // The address of this instruction is injected by `clone` in process.rs, on // top of the stack syscall->inner in this file, which is done using the rbp // register we save there. @@ -165,4 +178,5 @@ function!(clone_ret => { "pop rbp\n", // ...and we return to the address at the top of the stack "ret\n", -}); + ), options(noreturn)); +} -- GitLab