diff --git a/litebox_platform_lvbs/src/host/per_cpu_variables.rs b/litebox_platform_lvbs/src/host/per_cpu_variables.rs index de1787df9..5911eb89a 100644 --- a/litebox_platform_lvbs/src/host/per_cpu_variables.rs +++ b/litebox_platform_lvbs/src/host/per_cpu_variables.rs @@ -261,6 +261,8 @@ pub struct PerCpuVariablesAsm { vtl_return_addr: Cell, /// Scratch pad scratch: Cell, + /// User-mode RFLAGS captured at `syscall` entry + user_rflags: Cell, /// Top address of VTL0 VtlState vtl0_state_top_addr: Cell, /// Current kernel stack pointer @@ -358,6 +360,9 @@ impl PerCpuVariablesAsm { pub const fn scratch_offset() -> usize { offset_of!(PerCpuVariablesAsm, scratch) } + pub const fn user_rflags_offset() -> usize { + offset_of!(PerCpuVariablesAsm, user_rflags) + } pub const fn vtl0_state_top_addr_offset() -> usize { offset_of!(PerCpuVariablesAsm, vtl0_state_top_addr) } diff --git a/litebox_platform_lvbs/src/lib.rs b/litebox_platform_lvbs/src/lib.rs index ce933a727..80271ef06 100644 --- a/litebox_platform_lvbs/src/lib.rs +++ b/litebox_platform_lvbs/src/lib.rs @@ -1765,6 +1765,7 @@ macro_rules! XRSTOR_VTL1_ASM { /// /// Prerequisite: /// - Store user `rsp` in `r11` before calling this macro. +/// - Store user `rflags` in `gs:[user_rflags]` before calling this macro. /// - Store the userspace return address in `rcx` (`syscall` does this automatically). #[cfg(target_arch = "x86_64")] macro_rules! SAVE_SYSCALL_USER_CONTEXT_ASM { @@ -1772,7 +1773,7 @@ macro_rules! SAVE_SYSCALL_USER_CONTEXT_ASM { " push 0x2b // pt_regs->ss = __USER_DS push r11 // pt_regs->rsp - pushfq // pt_regs->eflags + push qword ptr gs:[{user_rflags_off}] // pt_regs->eflags push 0x33 // pt_regs->cs = __USER_CS push rcx // pt_regs->rip push rax // pt_regs->orig_rax @@ -1926,6 +1927,7 @@ unsafe extern "C" fn run_thread_arch( ".globl syscall_callback", "syscall_callback:", "swapgs", + "mov gs:[{user_rflags_off}], r11", // store user `rflags`. "mov r11, rsp", // store user `rsp` in `r11` "mov rsp, gs:[{user_context_top_off}]", // `rsp` points to the top address of user context area SAVE_SYSCALL_USER_CONTEXT_ASM!(), @@ -1945,6 +1947,8 @@ unsafe extern "C" fn run_thread_arch( // - GS = user (swapgs has NOT happened yet) ".globl exception_callback", "exception_callback:", + "cld", + "clac", "swapgs", "mov gs:[{scratch_off}], rax", // Save `rax` to per-CPU scratch "mov al, [rsp]", @@ -2038,6 +2042,7 @@ unsafe extern "C" fn run_thread_arch( vtl1_user_xsaved_off = const { PerCpuVariablesAsm::vtl1_user_xsaved_offset() }, USER_CONTEXT_SIZE = const core::mem::size_of::(), scratch_off = const { PerCpuVariablesAsm::scratch_offset() }, + user_rflags_off = const { PerCpuVariablesAsm::user_rflags_offset() }, exception_trapno_off = const { PerCpuVariablesAsm::exception_trapno_offset() }, is_in_user_off = const { PerCpuVariablesAsm::is_in_user_offset() }, init_handler = sym init_handler, diff --git a/litebox_platform_lvbs/src/syscall_entry.rs b/litebox_platform_lvbs/src/syscall_entry.rs index 2b2fb0a0f..7adc88b63 100644 --- a/litebox_platform_lvbs/src/syscall_entry.rs +++ b/litebox_platform_lvbs/src/syscall_entry.rs @@ -33,7 +33,20 @@ pub(crate) fn init() { let syscall_entry_addr = syscall_entry_wrapper as *const () as u64; LStar::write(VirtAddr::new(syscall_entry_addr)); - let rflags = RFlags::INTERRUPT_FLAG; + // Mask some important bits of the FLAGS register. + // + // - IF: to block interrupts during syscall handling + // - DF: to maintain the direction of some instructions like `movs` + // - AC: to maintain SMAP enforcement active + // - TF: to prevent kernel-mode single-stepping + // - NT and IOPL: Defense-in-depth. ring-3 should not be able to affect these bits. + let rflags = RFlags::INTERRUPT_FLAG + | RFlags::DIRECTION_FLAG + | RFlags::ALIGNMENT_CHECK + | RFlags::TRAP_FLAG + | RFlags::NESTED_TASK + | RFlags::IOPL_LOW + | RFlags::IOPL_HIGH; SFMask::write(rflags); // configure STAR MSR for CS/SS selectors diff --git a/litebox_runner_snp/src/entry.S b/litebox_runner_snp/src/entry.S index 937f1d098..8a2e79f6f 100644 --- a/litebox_runner_snp/src/entry.S +++ b/litebox_runner_snp/src/entry.S @@ -76,6 +76,7 @@ ignore_sysret: .org 0x120 entry_SYSCALL_64: + cld swapgs mov gs:0x0, rsp mov rsp, gs:0x8