#linux-kernel #sandbox #jail #command-line-tool #command-line-interface #infoarena

nightly bin+lib ia-sandbox

一个用于沙盒(监狱)和应用使用的命令行工具

5 个版本

使用旧的 Rust 2015

0.2.0 2018 年 8 月 10 日
0.1.3 2018 年 8 月 9 日
0.1.2 2018 年 8 月 9 日
0.1.1 2018 年 7 月 30 日
0.1.0 2018 年 7 月 30 日

#1659 in 命令行工具

MIT 许可证

98KB
2.5K SLoC

ia-sandbox

Infoarena 沙盒,用于运行用户提交的代码,使用 namespaces 和 cgroups 在 rust 中实现。

pipeline status License: MIT

目前还在开发中,属于实验性项目,请自行承担风险使用。

变更日志

请查看 变更日志 了解版本历史。

什么是 ia-sandbox?

ia-sandbox 是一个命令行工具,允许您以特定的限制运行不受信任的代码,例如在像 CodeforcesTopcoder 或它被设计的网站 Infoarena 上提交的代码,同时收集运行时信息和退出状态。

它使用现代 Linux 工具,因此需要相对较新的内核

  • cgroups v1 - Linux 内核的一个功能,用于限制、计账和隔离进程集合的资源使用
    • cpuacct - 用于精确的用户时间使用和限制,需要 64 位计算机以获得正确的精度。需要 Linux 内核 ≥ 2.6.24
    • memory - 用于内存使用和限制。需要 Linux 内核 ≥ 2.6.24
    • pids - 用于限制进程数量,对于防止 fork 毁弹是必要的。需要 Linux 内核 ≥ 4.3
  • linux namespaces - Linux 内核的另一个功能,用于在系统上隔离资源
    • mount - 用于隔离挂载点,隔离的应用程序只能看到自己以及调用者决定挂载到它旁边的任何内容。需要 Linux 内核 ≥ 2.4.19
    • ipc - 用于 ipc 隔离。需要 Linux 内核 ≥ 2.6.19
    • uts - 用于 uts 隔离。需要 Linux 内核 ≥ 2.6.19
    • pid - 用于隔离进程,沙盒中的应用程序将把自己视为整个系统上唯一的运行进程。需要 Linux 内核 ≥ 2.6.24
    • 网络 - 用于隔离网络接口,应用程序不能对网络进行任何更改,或看到外部更改。需要linux内核≥ 2.6.24
    • 用户命名空间 - 用于隔离用户ID和组ID。隔离的应用程序将在沙盒内将自己视为root,并且拥有所有能力,但在访问资源的目的上,实际上将是沙盒所有者的用户ID,从而大大限制应用程序可以执行的功能或利用。需要linux内核≥ 3.5,但为了确保安全性,最好使用≥ 3.9
    • cgroup - 用于隔离cgroup,不允许沙盒中的应用程序更改其自身的限制或使用情况。需要linux内核≥ 4.6

由于所有这些功能都需要激活,所需的最小版本是 4.6

安装

二进制名称是 ia-sandbox

安装此软件的最简单方法是使用Rust的包管理器cargo

  • ia-sandbox支持的最低Rust版本是 1.27.0,尽管ia-sandbox可能与较旧版本兼容。
cargo install ia-sandbox

为了实现实际隔离,最好更改沙盒的根目录(使用-r--new-root)。这将卸载除/proc之外的所有内容,后者是必要的,并且已经只显示隔离进程。

如果您想探索沙盒内部,一个简单的方法是

ia-sandbox --mount /lib:/lib:exec --mount /lib64:/lib64:exec --mount /usr:/usr:exec
           --mount /bin:/bin:exec --new-root PATH_TO_SOME_FOLDER --interactive --forward-env
           /bin/bash

它是如何工作的?

  • 它首先在一个新的PID和用户命名空间中启动一个supervisor进程(同时设置正确的uid,gid和proc挂载)。
  • 它将supervisor设置为在父进程死亡时终止。
  • 然后它启动将成为沙盒应用程序的实际进程。
    • 这样做是为了保护自己,以防父进程死亡,因为它是被迫终止的,而且没有人会杀死超出其限制的沙盒应用程序。根据pid命名空间的设计,如果命名空间中的init进程死亡,所有进程都会被杀死。
    • 此新进程在除了cgroup之外的所有命名空间中都是完全不同的。
  • 如果配置了,它将重定向标准输入和输出(同时它仍然可以访问文件路径)。
  • 它设置了堆栈限制。
    • 这与安全性无关,而是为了提供足够多的堆栈内存,使进程可以运行。
  • 它进入必要的cgroups(cpuacct,内存,pids),可选地不清除以前的运行的用量。
  • 它进入一个新的cgroup命名空间。
  • 如果请求新的根目录(通过--new-root-r),它将pivot roots到该路径
  • 它挂载/proc路径。
  • 它设置了uid/gid映射。
  • 它移动到不同的进程组。
  • 最后,它执行给定的应用程序。

贡献。

对于任何问题,尤其是安全相关的问题,请在问题中打开问题。

我无法对pull请求做出任何承诺,但我对此持开放态度 :-)。

如果您想运行测试,您需要首先构建测试固定装置,这可以很容易地完成

cargo build --features integration-test --bins

然后运行测试

cargo test

有需要夜间版特有功能的固定装置(例如内联汇编)。如果运行在夜间版,可以编译固定装置

cargo build --features integration-test,nightly --bins

然后运行测试

cargo test --features nightly

依赖项

~1.7–2.8MB
~48K SLoC