3个不稳定版本

0.2.1 2024年4月16日
0.2.0 2024年4月5日
0.1.0 2024年4月4日

#308 in Unix APIs

Download history 19/week @ 2024-04-18 1/week @ 2024-05-30 1/week @ 2024-06-27 4/week @ 2024-07-04

每月113次下载

MIT许可证

34KB
445

seccomp-stream

Crates.io Version docs.rs Codecov GitHub Actions Workflow Status

seccomp在内核版本5.0中由seccomp_unotify修改,增加了为seccomp事件添加用户空间通知器的功能。

已将其支持添加到libseccomp-rs,但它们的实现虽然完整,但却是阻塞的,因此不适合现代的异步Rust。

此crate旨在提供异步接收和回复这些通知的方式。

Cargo

cargo add seccomp-stream

seccomp-stream = "0.2"

使用方法

在接收通知后,您可以选择让系统调用通过并继续。然而,这却是不安全的,因为目标进程可能已经通过信号修改了参数。

有关更多信息,请参阅seccomp_unotify的手册页。

let mut stream = NotificationStream::new(fd).expect("Failed to construct NotificationStream");

while let Some(notification) = stream.next().await {
    unsafe { stream.send_continue(notification) }.unwrap();
}

或者,您可以选择在检查参数的有效性后,用目标进程替换系统调用。

虽然您可以使用Notification::open打开内存进行读写,但您会暴露自己于竞争条件。

根据手册页的说明,写入目标内存是绝对不安全的

let mut stream = NotificationStream::new(fd).expect("Failed to construct NotificationStream");

while let Some(notification) = stream.next().await {
    // Interact with the process in some way here
    stream
        .send(notification, ResponseType::Success(0))
        .expect("Failed to send response");
}

第三种选择是注入错误,阻止系统调用进一步进行。这将迫使目标进程使用其自己的错误处理。

let mut stream = NotificationStream::new(fd).expect("Failed to construct NotificationStream");

while let Some(notification) = stream.next().await {
    stream
        .send(notification, ResponseType::RawError(libc::EPERM))
        .expect("Failed to send response");
}

安全性

安装过滤器后,seccomp将返回一个文件描述符,可以用来通过epoll进行交互。

一旦epoll表明文件描述符可读,对ioctl的调用将不会阻塞。在其他任何情况下,调用都将阻塞。您可以选择以这种方式使用此库,但请注意混合阻塞和非阻塞方法可能会破坏阻塞保证。

之前概述的某些不应该做的事情。

  • 粗心大意地读取另一个进程的内存
  • 假设目标进程已完全停止
  • 写入另一个进程的内存

如果你信任目标进程,你可以选择仍然做这些事情,并且事情(可能)不会失控。

兼容性

该库需要以下内容存在

  • Linux内核版本5.0或更高
  • libseccomp和libseccomp-dev版本2.5或更高
  • 较新的Rust版本

依赖项

~3-11MB
~104K SLoC