Correctly preserve and set MXCSR and FCW.
This commit is contained in:
@@ -8,10 +8,22 @@ use core::arch::global_asm;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
global_asm!("
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
mov rdi, rsp
|
||||
and rsp, 0xFFFFFFFFFFFFFFF0
|
||||
|
||||
sub rsp, 8
|
||||
|
||||
mov DWORD PTR [rsp], 0x00001F80
|
||||
ldmxcsr [rsp]
|
||||
mov WORD PTR [rsp], 0x031F
|
||||
fldcw [rsp]
|
||||
|
||||
add rsp, 8
|
||||
|
||||
call relibc_start
|
||||
.size _start, . - _start
|
||||
");
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
global_asm!("
|
||||
|
||||
+12
-14
@@ -42,7 +42,7 @@ fn copy_str(cur_pid_fd: usize, new_pid_fd: usize, key: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn copy_float_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> {
|
||||
fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> {
|
||||
// Copy environment registers.
|
||||
{
|
||||
let cur_env_regs_fd = FdGuard::new(syscall::dup(cur_pid_fd, b"regs/env")?);
|
||||
@@ -52,15 +52,6 @@ fn copy_float_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> {
|
||||
let _ = syscall::read(*cur_env_regs_fd, &mut env_regs)?;
|
||||
let _ = syscall::write(*new_env_regs_fd, &env_regs)?;
|
||||
}
|
||||
// Copy float registers.
|
||||
{
|
||||
let cur_float_regs_fd = FdGuard::new(syscall::dup(cur_pid_fd, b"regs/float")?);
|
||||
let new_float_regs_fd = FdGuard::new(syscall::dup(new_pid_fd, b"regs/float")?);
|
||||
|
||||
let mut float_regs = syscall::FloatRegisters::default();
|
||||
let _ = syscall::read(*cur_float_regs_fd, &mut float_regs)?;
|
||||
let _ = syscall::write(*new_float_regs_fd, &float_regs)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -102,7 +93,7 @@ pub unsafe fn pte_clone_impl(stack: *mut usize) -> Result<usize> {
|
||||
let _ = syscall::write(*new_filetable_sel_fd, &usize::to_ne_bytes(*cur_filetable_fd))?;
|
||||
}
|
||||
|
||||
copy_float_env_regs(*cur_pid_fd, *new_pid_fd)?;
|
||||
copy_env_regs(*cur_pid_fd, *new_pid_fd)?;
|
||||
|
||||
// Unblock context.
|
||||
syscall::kill(new_pid, SIGCONT)?;
|
||||
@@ -204,7 +195,7 @@ fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
|
||||
let buf = create_set_addr_space_buf(*new_addr_space_fd, fork_ret as usize, initial_rsp as usize);
|
||||
let _ = syscall::write(*new_addr_space_sel_fd, &buf)?;
|
||||
}
|
||||
copy_float_env_regs(*cur_pid_fd, *new_pid_fd)?;
|
||||
copy_env_regs(*cur_pid_fd, *new_pid_fd)?;
|
||||
}
|
||||
// Copy the file table. We do this last to ensure that all previously used file descriptors are
|
||||
// closed. The only exception -- the filetable selection fd and the current filetable fd --
|
||||
@@ -248,7 +239,10 @@ fork_wrapper:
|
||||
push r14
|
||||
push r15
|
||||
|
||||
sub rsp, 16
|
||||
sub rsp, 32
|
||||
|
||||
stmxcsr [rsp+16]
|
||||
fnstcw [rsp+24]
|
||||
|
||||
mov rdi, rsp
|
||||
call __relibc_internal_fork_impl
|
||||
@@ -258,9 +252,13 @@ fork_ret:
|
||||
mov rdi, [rsp]
|
||||
mov rsi, [rsp + 8]
|
||||
call __relibc_internal_fork_hook
|
||||
|
||||
ldmxcsr [rsp+16]
|
||||
fldcw [rsp+24]
|
||||
|
||||
xor rax, rax
|
||||
2:
|
||||
add rsp, 16
|
||||
add rsp, 32
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
|
||||
@@ -45,9 +45,7 @@ where
|
||||
};
|
||||
let memory_fd = FdGuard::new(syscall::dup(*grants_fd, b"mem")?);
|
||||
|
||||
let instruction_ptr = usize::try_from(header.e_entry).map_err(|_| Error::new(ENOEXEC))?;
|
||||
|
||||
// Never allow more than 1 MiB of program headers. TODO: Capabilities again?
|
||||
// Never allow more than 1 MiB of program headers.
|
||||
const MAX_PH_SIZE: usize = 1024 * 1024;
|
||||
let phentsize = u64::from(header.e_phentsize) as usize;
|
||||
let phnum = u64::from(header.e_phnum) as usize;
|
||||
|
||||
Reference in New Issue
Block a user