From 07af4e49f7d0bbd46b98f4f93043595127c6c1ba Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 28 Sep 2024 16:51:17 +0200 Subject: [PATCH] Add sigaltstack test. --- src/header/signal/linux.rs | 49 +++++++++ src/platform/linux/signal.rs | 42 -------- tests/Makefile | 1 + tests/expected/bins_static/sigaltstack.stderr | 0 tests/expected/bins_static/sigaltstack.stdout | 101 ++++++++++++++++++ tests/sigaltstack.c | 83 ++++++++++++++ 6 files changed, 234 insertions(+), 42 deletions(-) create mode 100644 tests/expected/bins_static/sigaltstack.stderr create mode 100644 tests/expected/bins_static/sigaltstack.stdout create mode 100644 tests/sigaltstack.c diff --git a/src/header/signal/linux.rs b/src/header/signal/linux.rs index 217c1ff07..f30d0c350 100644 --- a/src/header/signal/linux.rs +++ b/src/header/signal/linux.rs @@ -1,3 +1,5 @@ +use super::{siginfo_t, sigset_t, stack_t}; +use crate::platform::types::*; use core::arch::global_asm; // Needs to be defined in assembly because it can't have a function prologue @@ -79,3 +81,50 @@ pub const SIGSTKSZ: usize = 8096; pub const SI_QUEUE: i32 = -1; pub const SI_USER: i32 = 0; + +// Mirrors the ucontext_t struct from the libc crate on Linux. + +pub(crate) type ucontext_t = ucontext; +pub(crate) type mcontext_t = mcontext; + +#[repr(C)] +pub struct ucontext { + pub uc_flags: c_ulong, + pub uc_link: *mut ucontext_t, + pub uc_stack: stack_t, + pub uc_mcontext: mcontext_t, + pub uc_sigmask: sigset_t, + __private: [u8; 512], +} + +#[repr(C)] +pub struct _libc_fpstate { + pub cwd: u16, + pub swd: u16, + pub ftw: u16, + pub fop: u16, + pub rip: u64, + pub rdp: u64, + pub mxcsr: u32, + pub mxcr_mask: u32, + pub _st: [_libc_fpxreg; 8], + pub _xmm: [_libc_xmmreg; 16], + __private: [u64; 12], +} +#[repr(C)] +pub struct _libc_fpxreg { + pub significand: [u16; 4], + pub exponent: u16, + __private: [u16; 3], +} + +#[repr(C)] +pub struct _libc_xmmreg { + pub element: [u32; 4], +} +#[repr(C)] +pub struct mcontext { + pub gregs: [i64; 23], // TODO: greg_t? + pub fpregs: *mut _libc_fpstate, + __private: [u64; 8], +} diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs index 27e4dcf63..139af7eff 100644 --- a/src/platform/linux/signal.rs +++ b/src/platform/linux/signal.rs @@ -14,48 +14,6 @@ use crate::{ }, }; -// Mirrors the ucontext_t struct from the libc crate on Linux. -#[repr(C)] -pub struct ucontext_t { - pub uc_flags: c_ulong, - pub uc_link: *mut ucontext_t, - pub uc_stack: stack_t, - pub uc_mcontext: mcontext_t, - pub uc_sigmask: sigset_t, - __private: [u8; 512], -} -#[repr(C)] -pub struct _libc_fpstate { - pub cwd: u16, - pub swd: u16, - pub ftw: u16, - pub fop: u16, - pub rip: u64, - pub rdp: u64, - pub mxcsr: u32, - pub mxcr_mask: u32, - pub _st: [_libc_fpxreg; 8], - pub _xmm: [_libc_xmmreg; 16], - __private: [u64; 12], -} -#[repr(C)] -pub struct _libc_fpxreg { - pub significand: [u16; 4], - pub exponent: u16, - __private: [u16; 3], -} - -#[repr(C)] -pub struct _libc_xmmreg { - pub element: [u32; 4], -} -#[repr(C)] -pub struct mcontext_t { - pub gregs: [i64; 23], // TODO: greg_t? - pub fpregs: *mut _libc_fpstate, - __private: [u64; 8], -} - impl PalSignal for Sys { unsafe fn getitimer(which: c_int, out: *mut itimerval) -> Result<()> { e_raw(syscall!(GETITIMER, which, out))?; diff --git a/tests/Makefile b/tests/Makefile index 73bb54dc2..8b50abbfe 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -30,6 +30,7 @@ EXPECT_NAMES=\ select \ setjmp \ sigaction \ + sigaltstack \ signal \ stdio/all \ stdio/buffer \ diff --git a/tests/expected/bins_static/sigaltstack.stderr b/tests/expected/bins_static/sigaltstack.stderr new file mode 100644 index 000000000..e69de29bb diff --git a/tests/expected/bins_static/sigaltstack.stdout b/tests/expected/bins_static/sigaltstack.stdout new file mode 100644 index 000000000..be1dfac34 --- /dev/null +++ b/tests/expected/bins_static/sigaltstack.stdout @@ -0,0 +1,101 @@ +SIGUSR2 handler00 +SIGUSR2 handler01 +SIGUSR2 handler02 +SIGUSR2 handler03 +SIGUSR2 handler04 +SIGUSR2 handler05 +SIGUSR2 handler06 +SIGUSR2 handler07 +SIGUSR2 handler08 +SIGUSR2 handler09 +SIGUSR2 handler10 +SIGUSR2 handler11 +SIGUSR2 handler12 +SIGUSR2 handler13 +SIGUSR2 handler14 +SIGUSR2 handler15 +SIGUSR2 handler16 +SIGUSR2 handler17 +SIGUSR2 handler18 +SIGUSR2 handler19 +SIGUSR2 handler20 +SIGUSR2 handler21 +SIGUSR2 handler22 +SIGUSR2 handler23 +SIGUSR2 handler24 +SIGUSR2 handler25 +SIGUSR2 handler26 +SIGUSR2 handler27 +SIGUSR2 handler28 +SIGUSR2 handler29 +SIGUSR2 handler30 +SIGUSR2 handler31 +SIGUSR2 handler32 +SIGUSR2 handler33 +SIGUSR2 handler34 +SIGUSR2 handler35 +SIGUSR2 handler36 +SIGUSR2 handler37 +SIGUSR2 handler38 +SIGUSR2 handler39 +SIGUSR2 handler40 +SIGUSR2 handler41 +SIGUSR2 handler42 +SIGUSR2 handler43 +SIGUSR2 handler44 +SIGUSR2 handler45 +SIGUSR2 handler46 +SIGUSR2 handler47 +SIGUSR2 handler48 +SIGUSR2 handler49 +SIGUSR2 handler50 +SIGUSR2 handler51 +SIGUSR2 handler52 +SIGUSR2 handler53 +SIGUSR2 handler54 +SIGUSR2 handler55 +SIGUSR2 handler56 +SIGUSR2 handler57 +SIGUSR2 handler58 +SIGUSR2 handler59 +SIGUSR2 handler60 +SIGUSR2 handler61 +SIGUSR2 handler62 +SIGUSR2 handler63 +SIGUSR2 handler64 +SIGUSR2 handler65 +SIGUSR2 handler66 +SIGUSR2 handler67 +SIGUSR2 handler68 +SIGUSR2 handler69 +SIGUSR2 handler70 +SIGUSR2 handler71 +SIGUSR2 handler72 +SIGUSR2 handler73 +SIGUSR2 handler74 +SIGUSR2 handler75 +SIGUSR2 handler76 +SIGUSR2 handler77 +SIGUSR2 handler78 +SIGUSR2 handler79 +SIGUSR2 handler80 +SIGUSR2 handler81 +SIGUSR2 handler82 +SIGUSR2 handler83 +SIGUSR2 handler84 +SIGUSR2 handler85 +SIGUSR2 handler86 +SIGUSR2 handler87 +SIGUSR2 handler88 +SIGUSR2 handler89 +SIGUSR2 handler90 +SIGUSR2 handler91 +SIGUSR2 handler92 +SIGUSR2 handler93 +SIGUSR2 handler94 +SIGUSR2 handler95 +SIGUSR2 handler96 +SIGUSR2 handler97 +SIGUSR2 handler98 +SIGUSR2 handler99 +SIGUSR2 handler00 diff --git a/tests/sigaltstack.c b/tests/sigaltstack.c new file mode 100644 index 000000000..22f575c99 --- /dev/null +++ b/tests/sigaltstack.c @@ -0,0 +1,83 @@ +#include <assert.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/mman.h> + +#include "test_helpers.h" + +size_t stack_size; +void *stack_base; + +volatile sig_atomic_t counter = 0; + +void action(int sig, siginfo_t *info, void *context_raw) { + assert(sig == SIGUSR2); + + ucontext_t *context = context_raw; + assert(context->uc_stack.ss_sp == stack_base); + assert(context->uc_stack.ss_size == stack_size); + + // TODO: Technically an implementation detail, but safe to check here. + assert((size_t)info >= (size_t)stack_base); + assert((size_t)info <= ((size_t)stack_base + stack_size)); + + int c = counter++; + + char str[] = "SIGUSR2 handlerXX\n"; + size_t len = strlen(str); + str[len - 2] = '0' + (c % 10); + str[len - 3] = '0' + ((c / 10) % 10); + write(STDOUT_FILENO, str, len); + + if (c < 100) { + raise(SIGUSR2); + } +} + +int main(void) { + int status; + + stack_size = 1024 * 1024; // TODO? + assert(stack_size >= MINSIGSTKSZ * 100); + stack_base = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ERROR_IF(mmap, stack_base, == MAP_FAILED); + + stack_t old_stack; + stack_t stack = (stack_t) { .ss_sp = stack_base, .ss_size = stack_size, .ss_flags = 0 }; + + status = sigaltstack(&stack, &old_stack); + ERROR_IF(sigaltstack, status, == -1); + + assert((old_stack.ss_flags & SS_ONSTACK) == 0); + + stack_t same; + + status = sigaltstack(&old_stack, &same); + ERROR_IF(sigaltstack, status, == -1); + assert(same.ss_sp == stack.ss_sp); + assert(same.ss_size == stack.ss_size); + assert((same.ss_flags & SS_ONSTACK) == 0); + + status = sigaltstack(&stack, NULL); + ERROR_IF(sigaltstack, status, == -1); + + status = sigaltstack(NULL, &same); + ERROR_IF(sigaltstack, status, == -1); + assert(same.ss_sp == stack.ss_sp); + assert(same.ss_size == stack.ss_size); + assert((same.ss_flags & SS_ONSTACK) == 0); + + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_NODEFER; + sa.sa_sigaction = action; + + status = sigaction(SIGUSR2, &sa, NULL); + ERROR_IF(sigaction, status, == -1); + + raise(SIGUSR2); + + return 0; +} -- GitLab