WIP: Let userspace manage fsbase/gsbase and TLS.

This commit is contained in:
4lDO2
2021-08-01 12:09:22 +02:00
parent 0968e4f87e
commit 3eedbeb14d
13 changed files with 283 additions and 214 deletions
+2 -19
View File
@@ -39,13 +39,6 @@
pub const USER_OFFSET: usize = 0;
pub const USER_PML4: usize = (USER_OFFSET & PML4_MASK)/PML4_SIZE;
/// Offset to user TCB
/// Each process has 4096 bytes, at an offset of 4096 * PID
// TODO: Get a real 64-bit offset, and allow loading ELF sections higher up than the current
// limit, iff the processor supports fsgsbase (in which case it is cheap to use 64-bit FS
// offsets).
pub const USER_TCB_OFFSET: usize = 0xB000_0000;
/// Offset to user arguments
pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2;
@@ -69,14 +62,8 @@
/// Size of user sigstack
pub const USER_SIGSTACK_SIZE: usize = 256 * 1024; // 256 KB
/// Offset to user TLS
pub const USER_TLS_OFFSET: usize = USER_SIGSTACK_OFFSET + PML4_SIZE;
pub const USER_TLS_PML4: usize = (USER_TLS_OFFSET & PML4_MASK)/PML4_SIZE;
// Maximum TLS allocated to each PID, should be approximately 8 MB
pub const USER_TLS_SIZE: usize = PML4_SIZE / 65536;
/// Offset to user temporary image (used when cloning)
pub const USER_TMP_OFFSET: usize = USER_TLS_OFFSET + PML4_SIZE;
pub const USER_TMP_OFFSET: usize = USER_SIGSTACK_OFFSET + PML4_SIZE;
pub const USER_TMP_PML4: usize = (USER_TMP_OFFSET & PML4_MASK)/PML4_SIZE;
/// Offset to user temporary heap (used when cloning)
@@ -95,10 +82,6 @@
pub const USER_TMP_SIGSTACK_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
pub const USER_TMP_SIGSTACK_PML4: usize = (USER_TMP_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;
/// Offset to user temporary tls (used when cloning)
pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_SIGSTACK_OFFSET + PML4_SIZE;
pub const USER_TMP_TLS_PML4: usize = (USER_TMP_TLS_OFFSET & PML4_MASK)/PML4_SIZE;
/// Offset for usage in other temporary pages
pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE;
pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_SIGSTACK_OFFSET + PML4_SIZE;
pub const USER_TMP_MISC_PML4: usize = (USER_TMP_MISC_OFFSET & PML4_MASK)/PML4_SIZE;
+5
View File
@@ -80,6 +80,11 @@ impl IretRegisters {
println!("RSP: {:>016X}", { self.rsp });
println!("SS: {:>016X}", { self.ss });
}
unsafe {
let fsbase = x86::msr::rdmsr(x86::msr::IA32_FS_BASE);
let gsbase = x86::msr::rdmsr(x86::msr::IA32_KERNEL_GSBASE);
println!("FSBASE {:>016X}\nGSBASE {:016X}", fsbase, gsbase);
}
}
}
+9 -5
View File
@@ -275,13 +275,13 @@ macro_rules! save_fsgsbase(
mov ecx, {MSR_FSBASE}
rdmsr
shl rdx, 32
mov edx, eax
or rdx, rax
mov r14, rdx
mov ecx, {MSR_GSBASE}
rdmsr
shl rdx, 32
mov edx, eax
or rdx, rax
mov r13, rdx
"
}
@@ -354,8 +354,11 @@ pub unsafe extern "C" fn usermode(_ip: usize, _sp: usize, _arg: usize, _is_singl
mov es, r15d
mov fs, r15d
mov gs, r15d
",
", restore_fsgsbase!(), "
// SS and CS will later be set via sysretq.
restore_fsgsbase!(), "
// Target instruction pointer
mov rcx, rdi
@@ -382,14 +385,15 @@ pub unsafe extern "C" fn usermode(_ip: usize, _sp: usize, _arg: usize, _is_singl
xor r15, r15
fninit
",
// NOTE: Regarding the sysretq vulnerability, this is safe as we cannot modify RCX,
// even though the caller can give us the wrong address. But, it's marked unsafe, so
// the caller is responsible for this! (And, the likelihood of rcx being changed in the
// middle here, is minimal, unless the attacker already has partial control of kernel
// memory.)
"
sysretq
"),
"),
flag_interrupts = const(FLAG_INTERRUPTS),
shift_singlestep = const(SHIFT_SINGLESTEP),