Commit 6a3825d4 authored by jD91mZM2's avatar jD91mZM2

WIP(ptrace): Only use non-signal stack when using a default handler

This is a curious problem and it's really hard to solve it in a way
that doesn't feel hacky. On one hand, of course you want to be able to
modify and intercept what happens when you use a signal, right? On the
other hand, changes made to the context (especially singlestepping)
while a signal is handled (such as `SIGSTOP`) are not preserved since
the stack is restored after the signal handler was invoked.

I think what we have in this change makes sense anyway, as we don't
really want users modifying registers and other data in the default
signal behavior that occurs **in kernel mode**. Also trying to use
`PTRACE_SINGLESTEP` will set the singlestep flag only if in a
user-mode signal handler, else it will set it on the instruction after
the signal handling, which I guess makes sense since it can't affect
the kernel-mode code that runs the default handler.

I don't know. Help. Pls.
parent 8695ecd8
......@@ -142,8 +142,8 @@ pub struct Context {
pub kfx: Option<Box<[u8]>>,
/// Kernel stack
pub kstack: Option<Box<[u8]>>,
/// Kernel signal backup
pub ksig: Option<(arch::Context, Option<Box<[u8]>>, Option<Box<[u8]>>)>,
/// Kernel signal backup: Registers, Kernel FX, Kernel Stack, Signal number
pub ksig: Option<(arch::Context, Option<Box<[u8]>>, Option<Box<[u8]>>, u8)>,
/// Restore ksig context on next switch
pub ksig_restore: bool,
/// Executable image
......
......@@ -6,6 +6,11 @@ use crate::start::usermode;
use crate::syscall;
use crate::syscall::flag::{SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU};
pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool {
let handler = handler.map(|ptr| ptr as usize).unwrap_or(0);
handler != SIG_DFL && handler != SIG_IGN
}
pub extern "C" fn signal_handler(sig: usize) {
let (action, restorer) = {
let contexts = contexts();
......
......@@ -151,7 +151,7 @@ pub unsafe fn switch() -> bool {
let arch = (&mut *to_ptr).arch.clone();
let kfx = (&mut *to_ptr).kfx.clone();
let kstack = (&mut *to_ptr).kstack.clone();
(&mut *to_ptr).ksig = Some((arch, kfx, kstack));
(&mut *to_ptr).ksig = Some((arch, kfx, kstack, sig));
(&mut *to_ptr).arch.signal_stack(signal_handler, sig);
}
......
......@@ -9,7 +9,7 @@ use crate::{
}
},
common::unique::Unique,
context::{self, Context, ContextId, Status},
context::{self, signal, Context, ContextId, Status},
event,
scheme::proc,
sync::WaitCondition
......@@ -328,18 +328,44 @@ pub unsafe fn rebase_regs_ptr_mut(
/// restored and otherwise undo all your changes. See `update(...)` in
/// context/switch.rs.
pub unsafe fn regs_for(context: &Context) -> Option<&InterruptStack> {
Some(&*match context.ksig {
Some((_, _, ref kstack)) => rebase_regs_ptr(context.regs, kstack.as_ref())?,
None => context.regs?.1.as_ptr()
})
let signal_backup_regs = match context.ksig {
None => None,
Some((_, _, ref kstack, signum)) => {
let is_user_handled = {
let actions = context.actions.lock();
signal::is_user_handled(actions[signum as usize].0.sa_handler)
};
if is_user_handled {
None
} else {
Some(rebase_regs_ptr(context.regs, kstack.as_ref())?)
}
}
};
signal_backup_regs
.or_else(|| context.regs.map(|regs| regs.1.as_ptr() as *const _))
.map(|ptr| &*ptr)
}
/// Mutable version of `regs_for`
pub unsafe fn regs_for_mut(context: &mut Context) -> Option<&mut InterruptStack> {
Some(&mut *match context.ksig {
Some((_, _, ref mut kstack)) => rebase_regs_ptr_mut(context.regs, kstack.as_mut())?,
None => context.regs?.1.as_ptr()
})
let signal_backup_regs = match context.ksig {
None => None,
Some((_, _, ref mut kstack, signum)) => {
let is_user_handled = {
let actions = context.actions.lock();
signal::is_user_handled(actions[signum as usize].0.sa_handler)
};
if is_user_handled {
None
} else {
Some(rebase_regs_ptr_mut(context.regs, kstack.as_mut())?)
}
}
};
signal_backup_regs
.or_else(|| context.regs.map(|regs| regs.1.as_ptr()))
.map(|ptr| &mut *ptr)
}
// __ __
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment