WIP: Signal handling

This commit is contained in:
Jeremy Soller
2017-07-09 21:34:38 -06:00
parent 7e52541f39
commit b5ff0aabd5
7 changed files with 151 additions and 47 deletions
+22 -3
View File
@@ -12,7 +12,7 @@ pub use self::process::*;
pub use self::time::*;
pub use self::validate::*;
use self::data::TimeSpec;
use self::data::{SigAction, TimeSpec};
use self::error::{Error, Result, ENOSYS};
use self::number::*;
@@ -70,7 +70,14 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
},
_ => match a {
SYS_YIELD => sched_yield(),
SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])),
SYS_NANOSLEEP => nanosleep(
validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?,
if c == 0 {
None
} else {
Some(validate_slice_mut(c as *mut TimeSpec, 1).map(|rem| &mut rem[0])?)
}
),
SYS_CLOCK_GETTIME => clock_gettime(b, validate_slice_mut(c as *mut TimeSpec, 1).map(|time| &mut time[0])?),
SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32),
SYS_BRK => brk(b),
@@ -80,7 +87,6 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
SYS_EXIT => exit((b & 0xFF) << 8),
SYS_KILL => kill(ContextId::from(b), c),
SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into),
SYS_SIGNAL => signal(b, c),
SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?),
SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
SYS_IOPL => iopl(b, stack),
@@ -95,6 +101,19 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
SYS_SETREUID => setreuid(b as u32, c as u32),
SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)),
SYS_SETREGID => setregid(b as u32, c as u32),
SYS_SIGACTION => sigaction(
b,
if c == 0 {
None
} else {
Some(validate_slice(c as *const SigAction, 1).map(|act| &act[0])?)
},
if d == 0 {
None
} else {
Some(validate_slice_mut(d as *mut SigAction, 1).map(|oldact| &mut oldact[0])?)
}
),
SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
SYS_PHYSALLOC => physalloc(b),
SYS_PHYSFREE => physfree(b, c),
+59 -15
View File
@@ -18,7 +18,7 @@ use context::ContextId;
use elf::{self, program_header};
use scheme::{self, FileHandle};
use syscall;
use syscall::data::Stat;
use syscall::data::{SigAction, Stat};
use syscall::error::*;
use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, O_CLOEXEC, SIG_DFL, WNOHANG};
use syscall::validate::{validate_slice, validate_slice_mut};
@@ -79,13 +79,14 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
let mut image = vec![];
let mut heap_option = None;
let mut stack_option = None;
let mut sigstack_option = None;
let mut tls_option = None;
let grants;
let name;
let cwd;
let env;
let files;
let handlers;
let actions;
// Copy from old process
{
@@ -195,6 +196,24 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
stack_option = Some(new_stack);
}
if let Some(ref sigstack) = context.sigstack {
let mut new_sigstack = context::memory::Memory::new(
VirtualAddress::new(::USER_TMP_SIGSTACK_OFFSET),
sigstack.size(),
entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE,
false
);
unsafe {
intrinsics::copy(sigstack.start_address().get() as *const u8,
new_sigstack.start_address().get() as *mut u8,
sigstack.size());
}
new_sigstack.remap(sigstack.flags());
sigstack_option = Some(new_sigstack);
}
if let Some(ref tls) = context.tls {
let mut new_tls = context::memory::Tls {
master: tls.master,
@@ -252,9 +271,9 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
}
if flags & CLONE_SIGHAND == CLONE_SIGHAND {
handlers = context.handlers.clone();
actions = context.actions.clone();
} else {
handlers = Arc::new(Mutex::new(context.handlers.lock().clone()));
actions = Arc::new(Mutex::new(context.actions.lock().clone()));
}
}
@@ -441,6 +460,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
context.stack = Some(stack);
}
// Setup user sigstack
if let Some(mut sigstack) = sigstack_option {
sigstack.move_to(VirtualAddress::new(::USER_SIGSTACK_OFFSET), &mut new_table, &mut temporary_page);
context.sigstack = Some(sigstack);
}
// Setup user TLS
if let Some(mut tls) = tls_option {
tls.mem.move_to(VirtualAddress::new(::USER_TLS_OFFSET), &mut new_table, &mut temporary_page);
@@ -455,7 +480,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
context.files = files;
context.handlers = handlers;
context.actions = actions;
}
}
@@ -470,12 +495,14 @@ fn empty(context: &mut context::Context, reaping: bool) {
assert!(context.image.is_empty());
assert!(context.heap.is_none());
assert!(context.stack.is_none());
assert!(context.sigstack.is_none());
assert!(context.tls.is_none());
} else {
// Unmap previous image, heap, grants, stack, and tls
context.image.clear();
drop(context.heap.take());
drop(context.stack.take());
drop(context.sigstack.take());
drop(context.tls.take());
}
@@ -673,6 +700,14 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
true
));
// Map stack
context.sigstack = Some(context::memory::Memory::new(
VirtualAddress::new(::USER_SIGSTACK_OFFSET),
::USER_SIGSTACK_SIZE,
entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
true
));
// Map TLS
if let Some((master, file_size, size)) = tls_option {
let tls = context::memory::Tls {
@@ -737,7 +772,12 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
let files = Arc::new(Mutex::new(context.files.lock().clone()));
context.files = files.clone();
context.handlers = Arc::new(Mutex::new(BTreeMap::new()));
context.actions = Arc::new(Mutex::new(vec![SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: 0,
sa_restorer: unsafe { mem::transmute(0usize) },
}; 128]));
let vfork = context.vfork;
context.vfork = false;
@@ -819,7 +859,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
}
// Go to usermode
unsafe { usermode(entry, sp); }
unsafe { usermode(entry, sp, 0); }
}
pub fn exit(status: usize) -> ! {
@@ -971,18 +1011,22 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
}
}
pub fn signal(sig: usize, handler: usize) -> Result<usize> {
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>) -> Result<usize> {
if sig > 0 && sig <= 0x7F {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut handlers = context.handlers.lock();
let previous = if handler == SIG_DFL {
handlers.remove(&(sig as u8))
} else {
handlers.insert(sig as u8, handler)
};
Ok(previous.unwrap_or(0))
let mut actions = context.actions.lock();
if let Some(oldact) = oldact_opt {
*oldact = actions[sig];
}
if let Some(act) = act_opt {
actions[sig] = *act;
}
Ok(0)
} else {
Err(Error::new(EINVAL))
}