Skip to main content

yule_sandbox/
lib.rs

1pub mod policy;
2
3#[cfg(target_os = "linux")]
4pub mod linux;
5
6#[cfg(target_os = "windows")]
7pub mod windows;
8
9#[cfg(target_os = "macos")]
10pub mod macos;
11
12use yule_core::error::Result;
13
14pub trait Sandbox: Send {
15    fn apply_to_current_process(&self, config: &SandboxConfig) -> Result<SandboxGuard>;
16    fn spawn(&self, config: &SandboxConfig) -> Result<SandboxedProcess>;
17}
18
19#[derive(Debug, Clone)]
20pub struct SandboxConfig {
21    pub model_path: std::path::PathBuf,
22    pub allow_gpu: bool,
23    pub max_memory_bytes: u64,
24    pub allow_network: bool,
25}
26
27pub struct SandboxedProcess {
28    pub pid: u32,
29    pub stdin: std::process::ChildStdin,
30    pub stdout: std::process::ChildStdout,
31}
32
33pub struct SandboxGuard {
34    #[cfg(target_os = "windows")]
35    pub(crate) job_handle: *mut std::ffi::c_void,
36    #[cfg(not(target_os = "windows"))]
37    _marker: (),
38}
39
40// job handle is just a kernel handle, safe to send across threads
41unsafe impl Send for SandboxGuard {}
42
43impl Drop for SandboxGuard {
44    fn drop(&mut self) {
45        #[cfg(target_os = "windows")]
46        {
47            if !self.job_handle.is_null() {
48                unsafe { windows::close_job_handle(self.job_handle); }
49            }
50        }
51    }
52}
53
54pub fn create_sandbox() -> Box<dyn Sandbox> {
55    #[cfg(target_os = "linux")]
56    { Box::new(linux::LinuxSandbox::new()) }
57
58    #[cfg(target_os = "windows")]
59    { Box::new(windows::WindowsSandbox::new()) }
60
61    #[cfg(target_os = "macos")]
62    { Box::new(macos::MacOsSandbox::new()) }
63}