isolate-integration 0.1.0

A Rust interface for the ioi/isolate sandbox program.
Documentation

Isolate Integration

这个 crate 提供了一个 Rust 接口来使用 ioi/isolate 沙箱程序。

使用 tokio 异步运行时来管理沙箱的生命周期和执行命令。

前提条件

首先,确保系统已安装 isolate。请参考 ioi/isolate

关于 isolate 的配置,参阅 isolate documentINSTALLATION 部分。

如果需要使用 cgroup 相关特性(推荐,如 --cg-mem 选项),请确保系统支持 cgroup v2。

基本用法

isolate 用法、选项含义等请参考 isolate document

下面是一个示例:

use isolate_integration::{IsolateSandbox, ResourceLimits};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建沙箱(默认启用 cgroup)
    let sandbox = IsolateSandbox::new(0)
        .with_stdin("input.txt")
        .with_stdout("output.txt")
        .with_stderr("error.txt");

    // 如果需要禁用 cgroup
    let sandbox_no_cg = IsolateSandbox::new(1)
        .disable_cgroups()
        .with_stdin("input.txt");

    // 设置资源限制
    let limits = ResourceLimits::new()
        .with_time_limit(1.0)      // 1 秒时间限制
        .with_cg_memory_limit(64 * 1024)  // 64 MB 内存限制
        .with_process_limit(1);        // 只允许 1 个进程

    // 初始化沙箱
    sandbox.init(&limits).await?;

    // 运行命令
    let result = sandbox.run("echo", ["Hello, World!"], &limits).await?;

    println!("exit code: {:?}", result.exit_code);
    println!("time: {:.3}s", result.time_used);
    println!("memory: {} KB", result.cg_memory_used);
    println!("output: {}", result.stdout);

    // 清理沙箱
    sandbox.cleanup().await?;
    
    Ok(())
}

高级配置

目录绑定

use isolate_integration::DirectoryRule;

let sandbox = IsolateSandbox::new(1)
    // 绑定外部目录到沙箱内部
    .with_directory_rule(DirectoryRule::bind("/tmp/work", "/tmp/sandbox_work").read_write())
    // 创建临时目录
    .with_directory_rule(DirectoryRule::tmp("/tmp/temp"))
    // 绑定系统目录(只读,禁止执行)
    .with_directory_rule(DirectoryRule::bind_same("/usr/bin").no_exec())
    // 挂载文件系统
    .with_directory_rule(DirectoryRule::filesystem("proc"));

环境变量

use isolate_integration::EnvRule;

let sandbox = IsolateSandbox::new(2)
    // 继承环境变量
    .with_env_rule(EnvRule::Inherit("HOME".to_string()))
    // 设置环境变量
    .with_env_rule(EnvRule::Set("PATH".to_string(), "/usr/bin:/bin".to_string()))
    // 继承所有环境变量
    .with_env_rule(EnvRule::FullEnv);

资源限制

let limits = ResourceLimits::new()
    .with_time_limit(2.0)              // CPU 时间限制
    .with_wall_time_limit(10.0)        // 墙钟时间限制
    .with_memory_limit(128 * 1024)     // 内存限制
    .with_cg_memory_limit(256 * 1024)  // 控制组内存限制
    .with_open_files_limit(64)         // 打开文件数限制
    .with_file_size_limit(1024)        // 单文件大小限制
    .with_process_limit(5);            // 进程数限制

特殊选项

let sandbox = IsolateSandbox::new(3)
    .use_cgroups()          // 启用控制组(默认已启用)
    .disable_cgroups()      // 禁用控制组
    .share_network()        // 共享网络命名空间
    .no_default_dirs()      // 不绑定默认目录
    .verbose();             // 详细输出

编译和运行示例

参见 examples/sandbox_usage.rs 中的完整示例, 运行示例:

cargo run --example sandbox_usage

API 简要参考

IsolateSandbox

主要的沙箱类,提供以下方法:

  • new(box_id: u32) - 创建新的沙箱实例
  • init(&self, limits: &ResourceLimits) - 初始化沙箱
  • run<I, S>(&self, program: &str, args: I, limits: &ResourceLimits) - 运行命令
  • cleanup(&self) - 清理沙箱
  • disable_cgroups(self) - 禁用控制组(如果不需要)

ResourceLimits

资源限制配置:

  • with_time_limit(seconds: f64) - 设置 CPU 时间限制
  • with_memory_limit(kb: u32) - 设置内存限制
  • with_wall_time_limit(seconds: f64) - 设置墙上时间限制
  • with_process_limit(count: u32) - 设置进程数限制。与 isolate--processes 选项不同,不给出该限制时允许无限制的进程数。

DirectoryRule

目录绑定规则:

  • bind(inside, outside) - 绑定外部目录
  • bind_same(path) - 绑定到相同路径
  • tmp(path) - 创建临时目录
  • filesystem(name) - 挂载文件系统

ExecutionResult

执行结果包含:

  • exit_code: Option<i32> - 退出码
  • signal: Option<i32> - 信号
  • time_used: f64 - CPU 时间
  • wall_time_used: f64 - 墙上时间
  • memory_used: u32 - 内存使用
  • killed: bool - 是否被杀死
  • stdout: String - 标准输出
  • stderr: String - 标准错误