Add posix_spawn support for Glibc

This commit is contained in:
LI Qing 2020-11-02 15:06:49 +08:00 committed by Zongmin.Gu
parent 40a52b56be
commit 318f1e6a4f
2 changed files with 121 additions and 4 deletions

@ -9,7 +9,7 @@ use crate::time::{timespec_t, ClockID};
use crate::util::mem_util::from_user::*; use crate::util::mem_util::from_user::*;
use std::ptr::NonNull; use std::ptr::NonNull;
pub fn do_spawn( pub fn do_spawn_for_musl(
child_pid_ptr: *mut u32, child_pid_ptr: *mut u32,
path: *const i8, path: *const i8,
argv: *const *const i8, argv: *const *const i8,
@ -36,7 +36,7 @@ pub fn do_spawn(
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
pub struct FdOp { pub struct FdOp {
// We actually switch the prev and next fields in the libc definition. // We actually switch the prev and next fields in the musl definition.
prev: *const FdOp, prev: *const FdOp,
next: *const FdOp, next: *const FdOp,
cmd: u32, cmd: u32,
@ -85,6 +85,122 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>> {
Ok(file_actions) Ok(file_actions)
} }
pub fn do_spawn_for_glibc(
child_pid_ptr: *mut u32,
path: *const i8,
argv: *const *const i8,
envp: *const *const i8,
fa: *const SpawnFileActions,
) -> Result<isize> {
check_mut_ptr(child_pid_ptr)?;
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
let argv = clone_cstrings_safely(argv)?;
let envp = clone_cstrings_safely(envp)?;
let file_actions = clone_file_actions_from_fa_safely(fa)?;
let current = current!();
debug!(
"spawn: path: {:?}, argv: {:?}, envp: {:?}, actions: {:?}",
path, argv, envp, file_actions
);
let child_pid = super::do_spawn::do_spawn(&path, &argv, &envp, &file_actions, &current)?;
unsafe { *child_pid_ptr = child_pid };
Ok(0)
}
#[repr(C)]
pub struct SpawnFileActions {
allocated: u32,
used: u32,
actions: *const SpawnAction,
pad: [u32; 16],
}
#[repr(C)]
struct SpawnAction {
tag: u32,
action: Action,
}
impl SpawnAction {
pub fn to_file_action(&self) -> Result<FileAction> {
#[deny(unreachable_patterns)]
Ok(match self.tag {
SPAWN_DO_CLOSE => FileAction::Close(unsafe { self.action.close_action.fd }),
SPAWN_DO_DUP2 => FileAction::Dup2(unsafe { self.action.dup2_action.fd }, unsafe {
self.action.dup2_action.newfd
}),
SPAWN_DO_OPEN => FileAction::Open {
path: clone_cstring_safely(unsafe { self.action.open_action.path })?
.to_string_lossy()
.into_owned(),
mode: unsafe { self.action.open_action.mode },
oflag: unsafe { self.action.open_action.oflag },
fd: unsafe { self.action.open_action.fd },
},
_ => return_errno!(EINVAL, "Unknown file action tag"),
})
}
}
// See <path_to_glibc>/posix/spawn_int.h
const SPAWN_DO_CLOSE: u32 = 0;
const SPAWN_DO_DUP2: u32 = 1;
const SPAWN_DO_OPEN: u32 = 2;
#[repr(C)]
union Action {
close_action: CloseAction,
dup2_action: Dup2Action,
open_action: OpenAction,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct CloseAction {
fd: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct Dup2Action {
fd: u32,
newfd: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct OpenAction {
fd: u32,
path: *const i8,
oflag: u32,
mode: u32,
}
fn clone_file_actions_from_fa_safely(fa_ptr: *const SpawnFileActions) -> Result<Vec<FileAction>> {
let mut file_actions = Vec::new();
if fa_ptr == std::ptr::null() {
return Ok(file_actions);
}
let sa_slice = {
check_ptr(fa_ptr)?;
let fa = unsafe { &*fa_ptr };
let sa_ptr = fa.actions;
let sa_len = fa.used as usize;
check_array(sa_ptr, sa_len)?;
unsafe { std::slice::from_raw_parts(sa_ptr, sa_len) }
};
for sa in sa_slice {
let file_action = sa.to_file_action()?;
file_actions.push(file_action);
}
Ok(file_actions)
}
pub fn do_clone( pub fn do_clone(
flags: u32, flags: u32,
stack_addr: usize, stack_addr: usize,

@ -42,7 +42,7 @@ use crate::net::{
use crate::process::{ use crate::process::{
do_arch_prctl, do_clone, do_exit, do_exit_group, do_futex, do_getegid, do_geteuid, do_getgid, do_arch_prctl, do_clone, do_exit, do_exit_group, do_futex, do_getegid, do_geteuid, do_getgid,
do_getpgid, do_getpid, do_getppid, do_gettid, do_getuid, do_prctl, do_set_tid_address, do_getpgid, do_getpid, do_getppid, do_gettid, do_getuid, do_prctl, do_set_tid_address,
do_spawn, do_wait4, pid_t, FdOp, ThreadStatus, do_spawn_for_glibc, do_spawn_for_musl, do_wait4, pid_t, FdOp, SpawnFileActions, ThreadStatus,
}; };
use crate::sched::{do_getcpu, do_sched_getaffinity, do_sched_setaffinity, do_sched_yield}; use crate::sched::{do_getcpu, do_sched_getaffinity, do_sched_setaffinity, do_sched_yield};
use crate::signal::{ use crate::signal::{
@ -412,7 +412,8 @@ macro_rules! process_syscall_table_with_callback {
(Mlock2 = 325) => handle_unsupported(), (Mlock2 = 325) => handle_unsupported(),
// Occlum-specific system calls // Occlum-specific system calls
(Spawn = 360) => do_spawn(child_pid_ptr: *mut u32, path: *const i8, argv: *const *const i8, envp: *const *const i8, fdop_list: *const FdOp), (SpawnGlibc = 359) => do_spawn_for_glibc(child_pid_ptr: *mut u32, path: *const i8, argv: *const *const i8, envp: *const *const i8, fa: *const SpawnFileActions),
(SpawnMusl = 360) => do_spawn_for_musl(child_pid_ptr: *mut u32, path: *const i8, argv: *const *const i8, envp: *const *const i8, fdop_list: *const FdOp),
(HandleException = 361) => do_handle_exception(info: *mut sgx_exception_info_t, fpregs: *mut FpRegs, context: *mut CpuContext), (HandleException = 361) => do_handle_exception(info: *mut sgx_exception_info_t, fpregs: *mut FpRegs, context: *mut CpuContext),
(HandleInterrupt = 362) => do_handle_interrupt(info: *mut sgx_interrupt_info_t, fpregs: *mut FpRegs, context: *mut CpuContext), (HandleInterrupt = 362) => do_handle_interrupt(info: *mut sgx_interrupt_info_t, fpregs: *mut FpRegs, context: *mut CpuContext),
} }