Force userspace to do post-syscall EINTR check.
This commit is contained in:
@@ -174,9 +174,10 @@ exception_stack!(synchronous_exception_at_el0, |stack| {
|
||||
match exception_code(stack.iret.esr_el1) {
|
||||
0b010101 => {
|
||||
let scratch = &stack.scratch;
|
||||
syscall::syscall(
|
||||
let ret = syscall::syscall(
|
||||
scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack,
|
||||
);
|
||||
scratch.x0 = ret;
|
||||
}
|
||||
|
||||
ty => {
|
||||
|
||||
@@ -132,10 +132,6 @@ impl InterruptStack {
|
||||
pub fn instr_pointer(&self) -> usize {
|
||||
self.iret.elr_el1
|
||||
}
|
||||
// TODO: This can maybe be done in userspace?
|
||||
pub fn set_syscall_ret_reg(&mut self, ret: usize) {
|
||||
self.scratch.x0 = ret;
|
||||
}
|
||||
pub fn dump(&self) {
|
||||
self.iret.dump();
|
||||
self.scratch.dump();
|
||||
|
||||
@@ -136,10 +136,6 @@ impl InterruptStack {
|
||||
pub fn set_instr_pointer(&mut self, eip: usize) {
|
||||
self.iret.eip = eip;
|
||||
}
|
||||
// TODO: This can maybe be done in userspace?
|
||||
pub fn set_syscall_ret_reg(&mut self, ret: usize) {
|
||||
self.scratch.eax = ret;
|
||||
}
|
||||
/// Loads all registers from a struct used by the proc:
|
||||
/// scheme to read/write registers.
|
||||
pub fn load(&mut self, all: &IntRegisters) {
|
||||
|
||||
@@ -30,7 +30,7 @@ interrupt_stack!(syscall, |stack| {
|
||||
with_interrupt_stack!(|stack| {
|
||||
let scratch = &stack.scratch;
|
||||
let preserved = &stack.preserved;
|
||||
syscall::syscall(
|
||||
let ret = syscall::syscall(
|
||||
scratch.eax,
|
||||
preserved.ebx,
|
||||
scratch.ecx,
|
||||
@@ -39,6 +39,7 @@ interrupt_stack!(syscall, |stack| {
|
||||
preserved.edi,
|
||||
stack,
|
||||
);
|
||||
stack.scratch.eax = ret;
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -116,10 +116,6 @@ impl InterruptStack {
|
||||
pub fn set_instr_pointer(&mut self, rip: usize) {
|
||||
self.iret.rip = rip;
|
||||
}
|
||||
// TODO: This can maybe be done in userspace?
|
||||
pub fn set_syscall_ret_reg(&mut self, ret: usize) {
|
||||
self.scratch.rax = ret;
|
||||
}
|
||||
|
||||
pub fn dump(&self) {
|
||||
self.iret.dump();
|
||||
|
||||
@@ -68,7 +68,7 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
|
||||
if allowed.unwrap_or(true) {
|
||||
let scratch = &(*stack).scratch;
|
||||
|
||||
syscall::syscall(
|
||||
let ret = syscall::syscall(
|
||||
scratch.rax,
|
||||
scratch.rdi,
|
||||
scratch.rsi,
|
||||
@@ -77,6 +77,7 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
|
||||
scratch.r8,
|
||||
&mut *stack,
|
||||
);
|
||||
(*stack).scratch.rax = ret;
|
||||
}
|
||||
|
||||
ptrace::breakpoint_callback(PTRACE_STOP_POST_SYSCALL, None);
|
||||
|
||||
+2
-10
@@ -67,7 +67,7 @@ pub fn syscall(
|
||||
e: usize,
|
||||
f: usize,
|
||||
stack: &mut InterruptStack,
|
||||
) {
|
||||
) -> usize {
|
||||
#[inline(always)]
|
||||
fn inner(
|
||||
a: usize,
|
||||
@@ -247,13 +247,5 @@ pub fn syscall(
|
||||
PercpuBlock::current().inside_syscall.set(false);
|
||||
|
||||
// errormux turns Result<usize> into -errno
|
||||
stack.set_syscall_ret_reg(Error::mux(result));
|
||||
|
||||
if result == Err(Error::new(EINTR)) {
|
||||
// Although it would be cleaner to simply run the signal trampoline right after switching
|
||||
// back to any given context, where the signal set/queue is nonempty, syscalls need to
|
||||
// complete *before* any signal is delivered. Otherwise the return value would probably be
|
||||
// overwritten.
|
||||
crate::context::signal::signal_handler();
|
||||
}
|
||||
Error::mux(result)
|
||||
}
|
||||
|
||||
+1
-1
Submodule syscall updated: bda8fe89c6...9609c7bc26
Reference in New Issue
Block a user