Skip to main content

test_exec_helper/
exec_helper.rs

1#![no_std]
2#![no_main]
3
4#[cfg(not(test))]
5use core::panic::PanicInfo;
6use strat9_syscall::{call, error::Error};
7
8const F_GETFD: usize = 1;
9const HELPER_FD: usize = 19;
10const SIGUSR1: usize = 10;
11const SIGUSR2: usize = 12;
12const SIG_IGN: u64 = 1;
13const SS_DISABLE: i32 = 1;
14
15#[repr(C)]
16#[derive(Clone, Copy)]
17struct SigActionRaw {
18    sa_handler: u64,
19    sa_flags: u64,
20    sa_restorer: u64,
21    sa_mask: u64,
22}
23
24#[repr(C)]
25#[derive(Clone, Copy)]
26struct SigStackRaw {
27    ss_sp: u64,
28    ss_flags: i32,
29    ss_size: usize,
30}
31
32fn write_fd(fd: usize, msg: &str) {
33    let _ = call::write(fd, msg.as_bytes());
34}
35
36fn log(msg: &str) {
37    write_fd(1, msg);
38}
39
40fn log_err(msg: &str) {
41    write_fd(2, msg);
42}
43
44fn check_sigaction(signum: usize, expected_handler: u64, label: &str) -> bool {
45    let mut old = SigActionRaw {
46        sa_handler: 0,
47        sa_flags: 0,
48        sa_restorer: 0,
49        sa_mask: 0,
50    };
51    match call::sigaction(signum, 0, &mut old as *mut _ as usize) {
52        Ok(_) if old.sa_handler == expected_handler => true,
53        Ok(_) => {
54            log_err("[test_exec_helper] ");
55            log_err(label);
56            log_err(" mismatch\n");
57            false
58        }
59        Err(err) => {
60            log_err("[test_exec_helper] ");
61            log_err(label);
62            log_err(": ");
63            log_err(err.name());
64            log_err("\n");
65            false
66        }
67    }
68}
69
70fn check_sigaltstack_reset() -> bool {
71    let mut old = SigStackRaw {
72        ss_sp: 0,
73        ss_flags: 0,
74        ss_size: 0,
75    };
76    match call::sigaltstack(0, &mut old as *mut _ as usize) {
77        Ok(_) if (old.ss_flags & SS_DISABLE) != 0 => true,
78        Ok(_) => {
79            log_err("[test_exec_helper] sigaltstack still enabled\n");
80            false
81        }
82        Err(err) => {
83            log_err("[test_exec_helper] sigaltstack query: ");
84            log_err(err.name());
85            log_err("\n");
86            false
87        }
88    }
89}
90
91fn check_cloexec_closed() -> bool {
92    match call::fcntl(HELPER_FD, F_GETFD, 0) {
93        Err(Error::BadHandle) => true,
94        Err(err) => {
95            log_err("[test_exec_helper] cloexec query: ");
96            log_err(err.name());
97            log_err("\n");
98            false
99        }
100        Ok(_) => {
101            log_err("[test_exec_helper] cloexec fd still open\n");
102            false
103        }
104    }
105}
106
107#[cfg(not(test))]
108#[panic_handler]
109fn panic(_info: &PanicInfo) -> ! {
110    log_err("[test_exec_helper] panic\n");
111    call::exit(210)
112}
113
114#[no_mangle]
115pub extern "C" fn _start() -> ! {
116    log("[test_exec_helper] validating post-exec state\n");
117
118    let mut ok = true;
119    ok &= check_sigaction(SIGUSR1, 0, "SIGUSR1 reset to default");
120    ok &= check_sigaction(SIGUSR2, SIG_IGN, "SIGUSR2 preserved as SIG_IGN");
121    ok &= check_sigaltstack_reset();
122    ok &= check_cloexec_closed();
123
124    if ok {
125        log("[test_exec_helper] validation passed\n");
126        call::exit(0)
127    } else {
128        call::exit(1)
129    }
130}