From ab738cede5c5156d3a55099a79284d431967285d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Jul 2017 20:08:57 -0600 Subject: [PATCH] Restore kernel parameters on sigreturn --- Cargo.toml | 2 +- src/context/context.rs | 22 +++++++++++++++------- src/context/switch.rs | 40 ++++++++++++++++++++++++++++++++++++++-- src/syscall/mod.rs | 4 +++- src/syscall/process.rs | 38 +++++++++++++++++++++++++++++--------- 5 files changed, 86 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 746c704..4aa934b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/context/context.rs b/src/context/context.rs index a059614..bae447e 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -65,6 +65,10 @@ pub struct Context { pub kfx: Option>, /// Kernel stack pub kstack: Option>, + /// 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, /// User heap @@ -88,7 +92,7 @@ pub struct Context { /// The open files in the scheme pub files: Arc>>>, /// Singal actions - pub actions: Arc>>, + pub actions: Arc>>, } 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])), } } diff --git a/src/context/switch.rs b/src/context/switch.rs index fdd0529..4706a11 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -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); diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 74c602e..8bfd132 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -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), diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 7fcc79d..f861635 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -378,6 +378,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { 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 { 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 { } } -pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>) -> Result { +pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>, restorer: usize) -> Result { 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 { + 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 { // Spin until not running let mut running = true;