#![forbid(unsafe_code)]
use std::{
fs::File,
sync::{Arc, Condvar, Mutex},
};
use ahash::HashMapExt;
use libseccomp::ScmpSyscall;
use nix::{errno::Errno, unistd::Pid};
use serde::{ser::SerializeMap, Serializer};
use crate::{
confine::{ScmpNotifReq, SydArch, SydMemoryMap},
elf::ExecutableFile,
fs::CanonicalPath,
hash::SydHashMap,
sigset::SydSigSet,
};
#[derive(Debug)]
pub struct SysInterrupt {
pub handler: Pid,
pub request: ScmpNotifReq,
pub ignore_restart: bool,
}
pub type BlockMap = SydHashMap<u64, SysInterrupt>;
pub type RestartMap = SydHashMap<Pid, SydSigSet>;
#[derive(Debug)]
pub struct SysInterruptMap {
pub sys_block: Arc<(Mutex<BlockMap>, Condvar)>,
pub sig_restart: Arc<Mutex<RestartMap>>,
}
#[derive(Debug)]
pub struct ExecResult {
pub(crate) exe: ExecutableFile,
pub(crate) file: File,
pub(crate) ip: u64,
pub(crate) sp: u64,
pub(crate) args: [u64; 6],
pub(crate) ip_mem: Option<[u8; 64]>,
pub(crate) sp_mem: Option<[u8; 64]>,
pub(crate) memmap: Option<Vec<SydMemoryMap>>,
}
pub type ErrorMap = SydHashMap<Pid, Option<Errno>>;
pub type ChdirMap<'a> = SydHashMap<Pid, CanonicalPath<'a>>;
pub type ExecvMap = SydHashMap<Pid, ExecResult>;
#[derive(Debug)]
pub struct SysResultMap<'a> {
pub trace_error: Arc<Mutex<ErrorMap>>,
pub trace_chdir: Arc<Mutex<ChdirMap<'a>>>,
pub trace_execv: Arc<Mutex<ExecvMap>>,
}
pub type SighandleMap = SydHashMap<Pid, u64>;
#[derive(Debug)]
pub struct SignalMap {
pub sig_handle: Arc<Mutex<SighandleMap>>,
}
impl SysInterrupt {
pub(crate) fn new(
request: ScmpNotifReq,
handler: Pid,
ignore_restart: bool,
) -> Result<Self, Errno> {
Ok(Self {
handler,
request,
ignore_restart,
})
}
}
impl serde::Serialize for SysInterrupt {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(3))?;
let data = &self.request.data;
let syscall = ScmpSyscall::get_name_by_arch(data.syscall, data.arch)
.unwrap_or_else(|_| format!("{}", i32::from(data.syscall)));
let _ = map.serialize_entry("pid", &self.request.pid);
let _ = map.serialize_entry("sys", &syscall);
let _ = map.serialize_entry("arch", &SydArch(data.arch));
let _ = map.serialize_entry("args", &data.args);
let _ = map.serialize_entry("handler", &self.handler.as_raw());
let _ = map.serialize_entry("ignore_restart", &self.ignore_restart);
map.end()
}
}
pub fn sys_interrupt_map_new() -> SysInterruptMap {
SysInterruptMap {
sys_block: Arc::new((Mutex::new(BlockMap::new()), Condvar::new())),
sig_restart: Arc::new(Mutex::new(RestartMap::new())),
}
}
pub fn sys_result_map_new<'a>() -> SysResultMap<'a> {
SysResultMap {
trace_error: Arc::new(Mutex::new(ErrorMap::new())),
trace_chdir: Arc::new(Mutex::new(ChdirMap::new())),
trace_execv: Arc::new(Mutex::new(ExecvMap::new())),
}
}
pub fn signal_map_new() -> SignalMap {
SignalMap {
sig_handle: Arc::new(Mutex::new(SighandleMap::new())),
}
}