//
// Syd: rock-solid application kernel
// src/kernel/ptrace/event/scmp.rs: ptrace(2) seccomp event handler
//
// Copyright (c) 2025 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

use std::sync::{Arc, RwLock};

use nix::{
    errno::Errno,
    sys::{
        ptrace,
        signal::{kill, Signal},
    },
    unistd::Pid,
};

use crate::{
    kernel::ptrace::handle_ptrace_sysenter, ptrace::ptrace_get_syscall_info, sandbox::Sandbox,
    workers::WorkerCache,
};

pub(crate) fn sysevent_scmp(pid: Pid, cache: &Arc<WorkerCache>, sandbox: &Arc<RwLock<Sandbox>>) {
    // This is ptrace syscall entry stop.
    //
    // SAFETY: Verify with PTRACE_GET_SYSCALL_INFO.
    let info = match ptrace_get_syscall_info(pid) {
        Ok(info) if info.seccomp().is_none() => {
            // unreachable!("BUG: Invalid syscall info returned by Linux: {info:?}")
            // trinity manages to reliably trigger this with op=0.
            // SAFETY: Failed to get syscall info but
            // process is still alive. Terminate!
            let _ = kill(pid, Some(Signal::SIGKILL));
            return;
        }
        Ok(info) => info,
        Err(Errno::ESRCH) => return,
        Err(_) => {
            // SAFETY: Failed to get syscall info but
            // process is still alive. Terminate!
            let _ = kill(pid, Some(Signal::SIGKILL));
            return;
        }
    };

    // Handle system call entry.
    let result = handle_ptrace_sysenter(pid, info, cache, sandbox);

    // Stop at syscall exit or continue as necessary.
    //
    // SAFETY: continue here is unsafe and we only use
    // it when skipping the system call.
    match result {
        Ok(_) => {
            let _ = ptrace::syscall(pid, None);
        }
        Err(Errno::ECANCELED) => {
            let _ = ptrace::cont(pid, None);
        }
        Err(Errno::ESRCH) => {}
        Err(_) => {
            // SAFETY: Unexpected error at sysenter,
            // terminate the process.
            let _ = kill(pid, Some(Signal::SIGKILL));
        }
    };
}
