#syscalls #security #seccomp #access-control #linux #landlock

extrasafe

通过减少代码可以访问的内容来使您的代码更加安全

9个版本 (4个重大更新)

0.5.1 2024年4月16日
0.5.0 2024年4月4日
0.4.0 2023年11月9日
0.3.0 2023年10月21日
0.1.2 2022年3月2日

#89 in Unix API

Download history 2/week @ 2024-05-15 6/week @ 2024-05-22 2/week @ 2024-05-29 5/week @ 2024-06-05 13/week @ 2024-07-03

529 monthly downloads
用于 zuk

MIT 许可证

105KB
1.5K SLoC

extrasafe

Coverage Status CI Status crates.io docs.rs

fn main() {
    println!("disabling syscalls...");

    extrasafe::SafetyContext::new()
        .enable(
           extrasafe::builtins::SystemIO::nothing()
              .allow_stdout()
              .allow_stderr()
   	    ).unwrap()
	.apply_to_all_threads().unwrap();

    // Opening files now fails!
    let res = File::create("should_fail.txt");
    assert!(res.is_err());

    println!("but printing to stdout still works!");
    eprintln!("and so does stderr!");
}

用户指南

您已经使用了安全和非安全Rust:现在您的代码可以更加安全。

extrasafe是一个易于使用的各种Linux安全工具的包装器,包括seccomp过滤器、syscall过滤功能,以防止您的程序调用不需要的syscalls,Landlock Linux安全模块以对IO操作进行更细粒度的控制,以及用户命名空间以实现更广泛的隔离。这些工具被systemd、Chrome、容器运行时和应用沙箱(如bubblewrap和firejail)使用。

extrasafe的目标是使您能够轻松地为您的程序添加额外的安全功能,而无需依赖运行软件的人进行外部配置。

seccomp非常简单,因此我们提供了简单的默认设置,使误用变得困难:默认拒绝,并预先选择了一组syscalls以启用。

此外,我们还支持一些稍微高级的使用案例

  • 仅允许读取/写入stdin/out/err
  • 允许读取/写入特定文件(在加载seccomp过滤器之前打开的文件)
  • 您可以通过实现RuleSet trait来定义自己的允许的syscalls集合。

我们还支持使用Landlock允许对文件系统的特定、有针对性的访问

fn main() {
    let tmp_dir = tempfile::tempdir().unwrap().into_path();

    extrasafe::SafetyContext::new()
        .enable(
           extrasafe::builtins::SystemIO::nothing()
              .allow_create_in_dir(&tmp_dir)
              .allow_write_file(&tmp_dir)
        ).unwrap()
	.apply_to_current_thread().unwrap();

    // Opening arbitrary files now fails!
    assert!(File::open("/etc/passwd")
        .is_err());

    // But the directory we allowed works
    assert!(File::create(tmp_dir.join("my_output.txt"))
        .is_ok());

    // And other syscalls are still disallowed
    assert!(std::net::UdpSocket::bind("127.0.0.1:0")
        .is_err());
}

有关通过extrasafe的Isolate使用用户命名空间以及关于extrasafe其余功能的更详细信息,请参阅此处用户指南并查看示例目录

extrasafe是为谁准备的?

应用程序开发者,他们想要严格控制他们的程序可以做什么和不能做什么。

如果您正在开发库,您有三件事情可以做

  1. 提供覆盖您的库功能的extrasafe::RuleSet
  2. 提供一种预先执行IO相关工作的init函数(例如:读取配置文件、SSL证书)。
  3. 如果你的库有任何独立的工作线程,你可以在工作线程中使用extrasafe。

你不想直接在库中使用extrasafe,因为你不知道你的依赖项将使用哪些功能。

目前extrasafe仅支持x86_64架构。如果你想支持其他架构,请提交一个问题。

其他用途

你可能能够使用extrasafe来帮助测试某些边缘情况,比如网络不可用或无法读取文件,但我想这个用例可能更适合由单独的库来处理。如果你感兴趣,请给我发邮件!

为什么?

这样你可以更加安全。假设你的程序有一个存在未知RCE的依赖项:extrasafe允许你通过禁用不需要的功能和文件来部分降低风险。

可以避免利用的特定漏洞示例(寻找贡献者!)

注意事项

Seccomp过滤器是一种相当粗糙的工具。

  • 它们不允许你在open调用中根据路径名进行过滤,或者实际上任何指向指针的syscall参数(但我们现在支持Landlock!)
  • 它们的最小作用域单位是线程,所以如果你想保护可能具有风险解析代码的热点内循环,你可能需要想出一种快速在现有线程之间传递数据的方法,而不是每次都启动一个新的线程。

为什么不使用X?

为什么不两者都使用?继续阅读。

为什么不使用systemd的内置seccomp支持?

systemd通过SystemCallFilter属性支持使用seccomp过滤子进程的syscall。参见这篇文章systemd文档

问题

  • Systemd特定的
  • 排除了为例如BSD编写后端使用pledge的情况
  • 不如细粒度
    • extrasafe允许你打开文件然后关闭进一步的访问,例如。
    • extrasafe允许你使用seccomp syscall参数过滤功能,例如,只接受在预先分配的套接字文件描述符上的连接。
  • 通过将安全配置文件放入代码中,它可以从维护代码库的所有工作中受益:源代码控制、自动化测试、代码覆盖率,因此你可以确保在代码部署的任何时间和地点,你的安全配置文件都符合指定。

对于那些正在阅读此文档并说“但是我不想相信开发者正确编写了他们的seccomp过滤器!”的系统管理员或DevOps人员——太好了!深度防御是我们的目标,你可以并且应该继续使用AppArmor或你偏好的外部安全控制系统。

那么AppArmor或SELinux呢?

如上所述,你应该继续使用AppArmor和SELinux等Linux安全模块!并不是每个程序都会使用extrasafe。

同样,从一个开发者的角度来看,也没有保证运行你代码的人在使用它们。当你的开源代码在成千上万的机器上运行(这些机器不在你的控制之下)并存在bug时,知道它不容易被利用并且可以在你的空闲时间修复,而不是需要协调大规模的补丁和升级工作来确保系统的安全,这要舒服得多。

开发

测试

make测试

代码检查 / clippy

make代码检查

代码覆盖率

make覆盖率

依赖关系

~1MB
~16K SLoC