From f91b90445d7eb7433af2f100fb3e73af9c1fbb7f Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 27 Jun 2024 21:49:19 +0200 Subject: [PATCH] Force userspace to do post-syscall EINTR check. --- src/arch/aarch64/interrupt/exception.rs | 3 ++- src/arch/aarch64/interrupt/handler.rs | 4 ---- src/arch/x86/interrupt/handler.rs | 4 ---- src/arch/x86/interrupt/syscall.rs | 3 ++- src/arch/x86_64/interrupt/handler.rs | 4 ---- src/arch/x86_64/interrupt/syscall.rs | 3 ++- src/syscall/mod.rs | 12 ++---------- syscall | 2 +- 8 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs index fc1b684382..cb84e6e7fc 100644 --- a/src/arch/aarch64/interrupt/exception.rs +++ b/src/arch/aarch64/interrupt/exception.rs @@ -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 => { diff --git a/src/arch/aarch64/interrupt/handler.rs b/src/arch/aarch64/interrupt/handler.rs index 42ab5e1ecb..79bc031b6c 100644 --- a/src/arch/aarch64/interrupt/handler.rs +++ b/src/arch/aarch64/interrupt/handler.rs @@ -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(); diff --git a/src/arch/x86/interrupt/handler.rs b/src/arch/x86/interrupt/handler.rs index b1dca99699..0973791db8 100644 --- a/src/arch/x86/interrupt/handler.rs +++ b/src/arch/x86/interrupt/handler.rs @@ -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) { diff --git a/src/arch/x86/interrupt/syscall.rs b/src/arch/x86/interrupt/syscall.rs index 9ee4c544f7..885aae0558 100644 --- a/src/arch/x86/interrupt/syscall.rs +++ b/src/arch/x86/interrupt/syscall.rs @@ -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; }) }); diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index 1e2d6f3ec7..f0cac19176 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -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(); diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index f533fa6ec3..af7043d9c0 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -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); diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 8080b192dc..c0823142b7 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -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 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) } diff --git a/syscall b/syscall index bda8fe89c6..9609c7bc26 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit bda8fe89c63e05db51ee4b5171e90d33a5580265 +Subproject commit 9609c7bc269bc24a487c0200e11639add4d43642