Restore kernel parameters on sigreturn

This commit is contained in:
Jeremy Soller
2017-07-10 20:08:57 -06:00
parent b5ff0aabd5
commit ab738cede5
5 changed files with 86 additions and 20 deletions

View File

@@ -13,7 +13,7 @@ alloc_kernel = { path = "alloc_kernel" }
bitflags = "0.7"
spin = "0.4"
raw-cpuid = { git = "https://github.com/gz/rust-cpuid", branch = "master" }
redox_syscall = "0.1"
redox_syscall = { version = "0.1", path = "/home/jeremy/Projects/syscall" }
[dependencies.goblin]
version = "0.0.10"

View File

@@ -65,6 +65,10 @@ pub struct Context {
pub kfx: Option<Box<[u8]>>,
/// Kernel stack
pub kstack: Option<Box<[u8]>>,
/// Kernel signal backup
pub ksig: Option<(arch::Context, Box<[u8]>, Box<[u8]>)>,
/// Restore ksig context on next switch
pub ksig_restore: bool,
/// Executable image
pub image: Vec<SharedMemory>,
/// User heap
@@ -88,7 +92,7 @@ pub struct Context {
/// The open files in the scheme
pub files: Arc<Mutex<Vec<Option<File>>>>,
/// Singal actions
pub actions: Arc<Mutex<Vec<SigAction>>>,
pub actions: Arc<Mutex<Vec<(SigAction, usize)>>>,
}
impl Context {
@@ -112,6 +116,8 @@ impl Context {
arch: arch::Context::new(),
kfx: None,
kstack: None,
ksig: None,
ksig_restore: false,
image: Vec::new(),
heap: None,
stack: None,
@@ -123,12 +129,14 @@ impl Context {
events: Arc::new(WaitQueue::new()),
env: Arc::new(Mutex::new(BTreeMap::new())),
files: Arc::new(Mutex::new(Vec::new())),
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])),
actions: Arc::new(Mutex::new(vec![(
SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: 0,
},
0
); 128])),
}
}

View File

@@ -47,6 +47,29 @@ pub unsafe fn switch() -> bool {
// println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock()));
}
if context.ksig_restore {
println!("Restore from ksig");
let ksig = context.ksig.take().expect("context::switch: ksig not set with ksig_restore");
context.arch = ksig.0;
if let Some(ref mut kfx) = context.kfx {
kfx.clone_from_slice(&ksig.1);
} else {
panic!("context::switch: kfx not set with ksig_restore");
}
if let Some(ref mut kstack) = context.kstack {
kstack.clone_from_slice(&ksig.2);
} else {
panic!("context::switch: kstack not set with ksig_restore");
}
context.ksig_restore = false;
//TODO: Interrupt
if context.status == Status::Blocked {
context.unblock();
}
}
if context.status == Status::Blocked && !context.pending.is_empty() {
context.unblock();
}
@@ -112,6 +135,20 @@ pub unsafe fn switch() -> bool {
arch::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
if let Some(sig) = to_sig {
//TODO: Allow nested signals
assert!((&mut *to_ptr).ksig.is_none());
let arch = (&mut *to_ptr).arch.clone();
let kfx = match (&mut *to_ptr).kfx {
Some(ref kfx) => kfx.clone(),
None => panic!("context::switch: no kfx during signal")
};
let kstack = match (&mut *to_ptr).kstack {
Some(ref kstack) => kstack.clone(),
None => panic!("context::switch: no kstack during signal")
};
(&mut *to_ptr).ksig = Some((arch, kfx, kstack));
(&mut *to_ptr).arch.signal_stack(signal_handler, sig);
}
@@ -121,7 +158,7 @@ pub unsafe fn switch() -> bool {
}
extern "C" fn signal_handler(sig: usize) {
let action = {
let (action, restorer) = {
let contexts = contexts();
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
let context = context_lock.read();
@@ -132,7 +169,6 @@ extern "C" fn signal_handler(sig: usize) {
println!("Signal handler: {:X}, {:?}", sig, action);
let handler = action.sa_handler as usize;
let restorer = action.sa_restorer as usize;
if handler == SIG_DFL {
println!("Exit {:X}", sig);
syscall::exit(sig);

View File

@@ -112,8 +112,10 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
None
} else {
Some(validate_slice_mut(d as *mut SigAction, 1).map(|oldact| &mut oldact[0])?)
}
},
e
),
SYS_SIGRETURN => sigreturn(),
SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
SYS_PHYSALLOC => physalloc(b),
SYS_PHYSFREE => physfree(b, c),

View File

@@ -378,6 +378,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
context.kstack = Some(stack);
}
// TODO: Clone ksig?
// Setup heap
if flags & CLONE_VM == CLONE_VM {
// Copy user image mapping, if found
@@ -772,12 +774,14 @@ 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.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]));
context.actions = Arc::new(Mutex::new(vec![(
SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: [0; 2],
sa_flags: 0,
},
0
); 128]));
let vfork = context.vfork;
context.vfork = false;
@@ -1011,7 +1015,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
}
}
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>) -> Result<usize> {
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>, restorer: usize) -> Result<usize> {
if sig > 0 && sig <= 0x7F {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -1019,11 +1023,11 @@ pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mu
let mut actions = context.actions.lock();
if let Some(oldact) = oldact_opt {
*oldact = actions[sig];
*oldact = actions[sig].0;
}
if let Some(act) = act_opt {
actions[sig] = *act;
actions[sig] = (*act, restorer);
}
Ok(0)
@@ -1032,6 +1036,22 @@ pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mu
}
}
pub fn sigreturn() -> Result<usize> {
println!("Sigreturn");
{
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let mut context = context_lock.write();
context.ksig_restore = true;
context.block();
}
unsafe { context::switch(); }
unreachable!();
}
fn reap(pid: ContextId) -> Result<ContextId> {
// Spin until not running
let mut running = true;