mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-24 20:28:06 +02:00
feat: Implement dynamic verification layer with harness generation and payload orchestration
This commit is contained in:
parent
fb698d2c27
commit
56e934656c
10 changed files with 582 additions and 0 deletions
90
src/dynamic/sandbox.rs
Normal file
90
src/dynamic/sandbox.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
//! Execution sandbox.
|
||||
//!
|
||||
//! The sandbox isolates a [`crate::dynamic::harness::BuiltHarness`] from
|
||||
//! the host: no outbound network except to the oracle's OOB host, no file
|
||||
//! writes outside the workdir, hard timeout, memory cap, no host PID
|
||||
//! visibility.
|
||||
//!
|
||||
//! Two backends planned, picked at runtime:
|
||||
//!
|
||||
//! - **`docker`**: portable, default on Linux/macOS. Image is a thin debian
|
||||
//! plus the language toolchain matching `spec.lang`.
|
||||
//! - **`process`**: fallback for hosts without docker. Uses OS primitives
|
||||
//! (`unshare` on Linux, `sandbox-exec` on macOS) and runs the harness
|
||||
//! directly. Less isolation; gated behind `--unsafe-sandbox`.
|
||||
//!
|
||||
//! All public state on the sandbox is owned by the caller — there is no
|
||||
//! global runtime, no daemon, no persistent containers between runs.
|
||||
|
||||
use crate::dynamic::corpus::Payload;
|
||||
use crate::dynamic::harness::BuiltHarness;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Result of a single sandboxed run.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SandboxOutcome {
|
||||
/// Process exit code; `None` on timeout or signal kill.
|
||||
pub exit_code: Option<i32>,
|
||||
/// Captured stdout (truncated to a bound, default 64 KiB).
|
||||
pub stdout: Vec<u8>,
|
||||
/// Captured stderr (same bound).
|
||||
pub stderr: Vec<u8>,
|
||||
/// Whether the run hit `timeout`.
|
||||
pub timed_out: bool,
|
||||
/// Whether the OOB host received a probe.
|
||||
pub oob_callback_seen: bool,
|
||||
/// Wall-clock duration of the run.
|
||||
pub duration: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SandboxOptions {
|
||||
/// Hard timeout. Default: 5s.
|
||||
pub timeout: Duration,
|
||||
/// Memory cap in MiB. Default: 256.
|
||||
pub memory_mib: u64,
|
||||
/// Backend selection. `Auto` = docker if available, else process.
|
||||
pub backend: SandboxBackend,
|
||||
}
|
||||
|
||||
impl Default for SandboxOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
timeout: Duration::from_secs(5),
|
||||
memory_mib: 256,
|
||||
backend: SandboxBackend::Auto,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SandboxBackend {
|
||||
Auto,
|
||||
Docker,
|
||||
Process,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SandboxError {
|
||||
BackendUnavailable(SandboxBackend),
|
||||
Spawn(std::io::Error),
|
||||
Io(std::io::Error),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for SandboxError {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
SandboxError::Io(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a built harness once with a chosen payload.
|
||||
///
|
||||
/// Stub: dispatches to one of the backend submodules
|
||||
/// (`sandbox/docker.rs`, `sandbox/process.rs`) once those land.
|
||||
pub fn run(
|
||||
_harness: &BuiltHarness,
|
||||
_payload: &Payload,
|
||||
_opts: &SandboxOptions,
|
||||
) -> Result<SandboxOutcome, SandboxError> {
|
||||
Err(SandboxError::BackendUnavailable(SandboxBackend::Auto))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue